2009-11-25 108 views
1

测试“多对多的关系”中的NHibernate当我测试多对多类出现错误:如何映射使用功能NHibernate

System.ApplicationException:实际 计数不等于预期计数。

实体:

public interface IEntity 
    { 
     int Id { get; set; } 
    } 

    public abstract class Entity : IEntity 
    { 
     public virtual int Id { get; set; } 

     public virtual bool IsPersistent 
     { 
      get { return isPersistentObject(); } 
     } 

     public override bool Equals(object obj) 
     { 
      if (isPersistentObject()) 
      { 
       var persistentObject = obj as Entity; 
       return (persistentObject != null) && (Id == persistentObject.Id); 
      } 

      return base.Equals(obj); 
     } 

     public override int GetHashCode() 
     { 
      return isPersistentObject() ? Id.GetHashCode() : base.GetHashCode(); 
     } 

     private bool isPersistentObject() 
     { 
      return (Id != 0); 
     } 
    } 

    public class Team : Entity 
    { 
     public virtual string Name { get; set; } 
     public virtual ISet<Employee> Employees { get; set; } 

     public Team() 
     { 
      Employees = new HashedSet<Employee>(); 
     } 
    } 

    public class Employee : Entity 
    { 
     public virtual string LastName { get; set; } 
     public virtual string FirstName { get; set; } 
     public virtual ISet<Team> Teams { get; set; } 
     public virtual string EMail { get; set; } 

     public Employee() 
     { 
      Teams = new HashedSet<Team>(); 
     } 
    } 

映射:

public class TeamMap : ClassMap<Team> 
{ 
    public TeamMap() 
    { 
     // identity mapping 
     Id(p => p.Id).Column("TeamID"); 

     // column mapping 
     Map(p => p.Name); 

     // relationship mapping 
     HasManyToMany(m => m.Employees) 
      .Table("EmployeeTeam") 
      .LazyLoad() 
      .Cascade.SaveUpdate() 
      .AsSet() 
      .ParentKeyColumn("TeamID") 
      .ChildKeyColumn("EmployeeID"); 
    } 
} 

public class EmployeeMap : ClassMap<Employee> 
{ 
    public EmployeeMap() 
    { 
     // identifier mapping 
     Id(p => p.Id).Column("EmployeeID"); 

     // column mapping 
     Map(p => p.EMail); 
     Map(p => p.LastName); 
     Map(p => p.FirstName); 

     // relationship mapping 
     HasManyToMany(m => m.Teams).Table("EmployeeTeam") 
      .Inverse() 
      .Cascade.SaveUpdate() 
      .AsSet() 
      .LazyLoad() 
      .ParentKeyColumn("EmployeeID") 
      .ChildKeyColumn("TeamID"); 
    } 
} 

测试:

[TestMethod] 
public void CanCorrectlyMapEmployee() 
{ 
    var team = new List<Team> {new Team() {Name = "Team1"}}; 

    new PersistenceSpecification<Employee>(_session) 
     .CheckProperty(p => p.EMail, "Mail") 
     .CheckProperty(p => p.FirstName, "Firstname") 
     .CheckProperty(p => p.Id, 1) 
     .CheckProperty(p => p.LastName, "Lastname") 
     .CheckList(p => p.Teams,team) 
     .VerifyTheMappings(); 
} 

我是否添加员工或团队我EmployeeTeam表总是空的。

我与FNH测试它针对SQLLite和手动对SQL Server 2008

难道你们任何人有一个想法,以解决这一问题?

编辑:

我惊奇地发现,当我创建一个员工,并添加2队的员工,并加载创建的员工,他有2个团队。所以它工作正常。但是当我查看我的关系表EmployeeTeam时,一切都是空的。有人可以解释我为什么吗?

是否有人知道我可以如何使用流利NHibernate来测试我的多对多关系?

在此先感谢!

回答

3

员工地图具有反向属性。您可能知道,这意味着当您保存员工时,关系表(EmployeeTeam)将不会更新。要添加/删除新的关系信息,您必须将员工添加到团队并保存团队。

因此,就你的情况而言 - 不要在员工身上测试多人,在团队一方进行测试。 (如果你希望NHibernate在将团队添加到员工时添加记录,则必须反转“反向”属性 - 将其分配给团队,而不是员工,但随后 - 与团队实体一样)。

为什么你可以加载员工与团队?由于会话级缓存。你可能在同一个ISession中保存和加载Employee - 这意味着NHibernate返回的是对同一个对象的引用,而不是从db中加载它。尝试在两个不同的会话中保存&加载,您将在Employee.Teams中设置任何团队。

备注:创建方法可以增强多对多关系的一致性,也就是说,当您将Team添加到Employee时,Employee会添加到团队中,这是一种很好的做法。像这样:

class Employee 
{ 
    // ... 
    public void AddTeam(Team team) 
    { 
    // check for null, etc. 

    Teams.Add(team); 
    team.Employees.Add(this); 
    } 
} 

和非常类似于Team类的方法。

+0

以及我错过了stackoverflow上的引用函数......“[...]因为会话级别的缓存,你可能在同一个ISession中保存和加载Employee - 这意味着NHibernate返回的是对同一个对象,而不需要从db中加载它。“这是不正确的。我测试了这一点,是的NHibernate缓存我的对象,但我清除缓存,然后加载我的对象。此外,我使用了SQL Server Profiler,在那里我看到了一个选择带有LEFT OUTER JOIN的查询。所以检索和保存工作,奇怪。但我会尝试一下你的提示。现在感谢。 – Rookian 2009-11-26 10:14:34

+0

为什么这段关系是空的问题,是因为我没有刷新会话。现在员工和团队可以正确保存。 – Rookian 2009-11-26 12:58:30