【问题标题】:Fluent NHibernate Many to one mappingFluent NHibernate 多对一映射
【发布时间】:2011-01-29 04:43:03
【问题描述】:

我是 Hibernate 世界的新手。这可能是一个愚蠢的问题,但我无法解决它。我正在测试表的多对一关系并尝试插入记录。我有一个部门表和员工表。 Employee 和 Dept 在这里有多对一的关系。我正在使用 Fluent NHibernate 添加记录。以下所有代码。请帮忙

SQL 代码

create table Dept (
    Id int primary key identity,
    DeptName varchar(20),
    DeptLocation varchar(20)
);

create table Employee (
    Id int primary key identity,
    EmpName varchar(20),
    EmpAge int,
    DeptId int references Dept(Id)
);

类文件

public partial class Dept
{
    public virtual System.String DeptLocation { get; set; }
    public virtual System.String DeptName { get; set; }
    public virtual System.Int32 Id { get; private  set; }
    public virtual IList<Employee> Employees { get; set; }
}

public partial class Employee
{
    public virtual System.Int32 DeptId { get; set; }
    public virtual System.Int32 EmpAge { get; set; }
    public virtual System.String EmpName { get; set; }
    public virtual System.Int32 Id { get; private set; }
    public virtual Project.Model.Dept Dept { get; set; }
}

映射文件

public class DeptMapping : ClassMap<Dept>   
{
    public DeptMapping()
    {
        Id(x => x.Id);
        Map(x => x.DeptName);
        Map(x => x.DeptLocation);
        HasMany(x => x.Employees).Inverse().Cascade.All();
    }
}

public class EmployeeMapping : ClassMap<Employee>
{
    public EmployeeMapping()
    {
        Id(x => x.Id);
        Map(x => x.EmpName);
        Map(x => x.EmpAge);
        Map(x => x.DeptId);
        References(x => x.Dept).Cascade.None();
    }
}

我要添加的代码

        try
        {
            Dept dept = new Dept();
            dept.DeptLocation = "Austin";
            dept.DeptName = "Store";

            Employee emp = new Employee();
            emp.EmpName = "Ron";
            emp.EmpAge = 30;

            IList<Employee> empList = new List<Employee>();
            empList.Add(emp);
            dept.Employees = empList;
            emp.Dept = dept;

            IRepository<Dept> rDept = new Repository<Dept>();
            rDept.SaveOrUpdate(dept);
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }

这里我遇到了错误

InnerException = {"无效的列名'Dept_id'。"} Message = "无法插入:[Project.Model.Employee][SQL: INSERT INTO [Employee] (EmpName, EmpAge, DeptId, Dept_id) VALUES (?, ?, ?, ?);选择 SCOPE_IDENTITY()]"

【问题讨论】:

标签: nhibernate nhibernate-mapping fluent


【解决方案1】:

问题是(正如错误消息告诉您的那样)您没有名为“Dept_id”的列。您的列名改为“DeptId”。 fluent nhibernate 的默认约定是名称应带有下划线。要解决这个问题,您可以更改数据库中列的名称,或者您可以覆盖映射文件中的约定以告诉它使用您的列名。可以通过这种方式完成:

//EmployeeMapping
References(x => x.Dept).ForeignKey("DeptId").Cascade.None();

//DeptMapping
HasMany(x => x.Employees).KeyColumn("DeptId").Inverse() .Cascade.All();

【讨论】:

  • 我按照您所说的进行了更改。我仍然遇到同样的错误。公共 DeptMapping() { Id(x => x.Id);地图(x => x.DeptName);地图(x => x.DeptLocation); HasMany(x => x.Employees) .KeyColumn("DeptId") .Inverse() .Cascade.All(); } public EmployeeMapping() { Id(x => x.Id);地图(x => x.EmpName);地图(x => x.EmpAge);地图(x => x.DeptId); References(x => x.Dept) .ForeignKey("DeptId") .Cascade.None(); }
【解决方案2】:

Mattias 的回答几乎是正确的,但 ForeignKey 用于模式生成。请尝试以下映射。此外,您还有用 CascadeAll 映射的员工集合。如果您删除一个部门,这将删除员工记录,这可能是不可取的。

public class DeptMapping : ClassMap<Dept>
    { 
        public DeptMapping() 
        {
            Id(x => x.Id); 
            Map(x => x.DeptName); 
            Map(x => x.DeptLocation); 
            HasMany(x => x.Employees).KeyColumn("DeptId").Inverse().Cascade.All(); 
        } 
    }

public class EmployeeMapping : ClassMap<Employee>
{ 
    public EmployeeMapping() 
    { 
        Id(x => x.Id); 
        Map(x => x.EmpName); 
        Map(x => x.EmpAge); 
        Map(x => x.DeptId); 
        References(x => x.Dept, "DeptId").Cascade.None(); 
   } 
}

【讨论】:

  • Jamie,感谢您的更正,我可以将记录插入到 Dept 表中。但它没有向 Employee 表插入记录。看起来我调用 SaveOrUpdate 部分的编码有一些错误。我几乎就在那里,但不是最后。
  • dept.Employees = empList; 行更改了集合引用。您需要通过dept.Employees.Add(emp);将员工添加到集合中。
  • 我用 dept.Employees.Add(emp) 替换了 dept.Employees= empList ,它给了对象引用而不是对象的设置实例。这是正确的,因为 EmployeeColleciton 为空。员工是一个 IList 集合,需要先设置,然后再添加项目。所以它不起作用。第二件事,如何改变集合引用?
  • 您应该在 Dept 的构造函数中初始化集合:Employees = new List&lt;Employee&gt;()。针对第二个问题,NHibernate 为 IList 提供了自己的集合实现,因此当您分配 deptEmployees = empList 时,引用已从 NHibernate 的列表更改为您的。
  • 天哪!为什么ManyToOne突然被称为“References”?我想责骂 Fluent Nhibernate 作者浪费我的时间。
【解决方案3】:
[Serializable] 
public partial class Dept   
{       
    public virtual System.String DeptLocation { get; set; }

    public virtual System.String DeptName { get; set; }

    public virtual System.Int32 Id { get; private  set; }   

    //public virtual Iesi.Collections.Generic.ISet<Employee> Employees { get; set; }

    public virtual IList<Employee> Employees { get; set; }

    public Dept()
    {
        Employees = new List<Employee>();      
    }

    public virtual void AddEmployees(Employee employee)
    {
        employee.Dept = this;
        Employees.Add(employee);       
    } 
}

员工类

public partial class Employee
{
    //public virtual System.Int32 DeptId { get; set; }
    public virtual System.Int32 EmpAge { get; set; }
    public virtual System.String EmpName { get; set; }
    public virtual System.Int32 Id { get; private set; }
    public virtual Project.Model.Dept  Dept { get; set; }
}

调用方法的代码

try
{
    Dept dept = new Dept();
    dept.DeptLocation = "Austin";
    dept.DeptName = "Store";

    Employee emp = new Employee();
    emp.EmpName = "Ron";
    emp.EmpAge = 30;


    dept.AddEmployees(emp); 


    IRepository<Dept> rDept = new Repository<Dept>();
    rDept.Add(dept);
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-07-17
    • 1970-01-01
    • 2010-12-07
    • 1970-01-01
    • 2012-02-24
    • 1970-01-01
    相关资源
    最近更新 更多