1

当我测试我的多对多类时,会发生错误:

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 时,一切都是空的。有人可以解释我为什么吗?

有人知道我如何使用 Fluent NHibernate 来测试我的多对多关系吗?

提前致谢!

4

1 回答 1

3

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

因此,就您而言-不要在员工方面进行多对多的测试,而是在团队方面进行测试。(如果您希望 NHibernate 在将团队添加到员工时添加记录,则必须反转“反向”属性 - 将其提供给团队,而不是员工,然后 - 与团队实体相同)。

为什么您能够为 Employee 加载团队?因为会话级缓存。您可能已经在同一个 ISession 中保存和加载了 Employee - 这意味着 NHibernate 返回您对同一对象的完全引用,而不是从数据库加载它。尝试在两个不同的会话中保存和加载,您将在 Employee.Teams 集中看到没有团队。

旁注:创建将强制多对多关系之间保持一致性的方法被认为是一种很好的做法,即 - 当您将团队添加到员工时,员工会添加到团队中,...... 像这样:

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

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

和 Team 类中非常相似的方法。

于 2009-11-26T09:23:46.567 回答