流利的Nhibernate多对多问题

时间:2010-12-15 17:05:40

标签: nhibernate fluent-nhibernate nhibernate-mapping

我有三张桌子:

  1. 人(Id,FirstName)
  2. 组织(身份证,姓名)
  3. PersonOrganization(PersonId,OrganizationId,Details)多对多表
  4. 当我第一次使用Fluent NHibernate映射它时,我在PersonOrganization表中没有详细信息列,并在PersonMap和OrganizationMap中使用HasManyToMany映射它(不需要创建PersonOrganization域对象或映射)。我可以写下面的代码:

    Organization org = new Organization { Name = "org" };
    People people = new People { FirstName = "firstname", Organization = org };
    
    peopleRepository.Add(people);          // ISession.Save(people)
    unitOfWork.Commit();                   // ITransaction.Commit()
    

    NHhibernate愉快地将数据提交给所有三个表。

    当我在PersonOrganization表中添加详细信息列时,问题出现了。经过一些研究后发现,我现在必须创建一个新的PersonOrganization域对象,并为Person和Organization映射和设置HasMany关系。我的更新模型和地图如下:

    public class People
    {
        public People()
        {
            LinkToOrganization = new List<PeopleOrganization>();
        }
    
        public virtual int Id { get; set; }
        public virtual string FirstName { get; set; }
        public virtual IList<PeopleOrganization> LinkToOrganization { get; set; }
    }
    
    public class Organization
    {
        public Organization()
        {
            LinkToPeople = new List<PeopleOrganization>();
        }
    
        public virtual int Id { get; set; }
        public virtual string Name { get; set; }
        public virtual IList<PeopleOrganization> LinkToPeople { get; set; }
    }
    
    public class PeopleOrganization
    {
        public virtual People People { get; set; }
        public virtual Organization Organization { get; set; }
        public virtual string Details { get; set; }
    }
    
    public class PeopleMap : ClassMap<People>
    {
        public PeopleMap()
        {
            Id(p => p.Id);
            Map(p => p.FirstName).Length(100);
    
            HasMany(x => x.LinkToOrganization)
                .Table("PeopleOrganization")
                .KeyColumn("PeopleId")
                .AsBag()
                .Inverse();
        }
    }
    
    public class OrganizationMap : ClassMap<Organization>
    {
        public OrganizationMap()
        {
            Id(p => p.Id);
            Map(p => p.Name).Length(50);
    
            HasMany(x => x.LinkToPeople)
                .Table("PeopleOrganization")
                .KeyColumn("OrganizationId")
                .AsBag()
                .Inverse();
        }
    }
    
    public class PeopleOrganizationMap : ClassMap<PeopleOrganization>
    {
        public PeopleOrganizationMap()
        {
            CompositeId()
                .KeyReference(p => p.People, "PeopleId")
                .KeyReference(p => p.Organization, "OrganizationId");
    
            Map(p => p.Details).Length(100);
        }
    }
    

    我现在必须编写以下代码:

    People people = new People { FirstName = "firstname" };
    Organization org = new Organization { Name = "org" };
    PeopleOrganization po = new PeopleOrganization { People = people, Organization = org, Details = "details" };
    
    peopleRepository.Add(people);          // ITransaction.Begin() ISession.Save(people)
    organizationRepository.Add(org);       // ISession.Save(org)
    peopleOrganizationRepository.Add(po);  // ISession.Save(po)
    
    unitOfWork.Commit();                   // ITransaction.Commit()
    

    我的问题是:

    1. 我的映射是否正确设置为支持这种多对多方案?
    2. 我是否有办法让我能够做到以下(这将写入所有三个表):
    3. -

      People people = new People { FirstName = "firstname" };
      Organization org = new Organization { Name = "org" };
      PeopleOrganization po = new PeopleOrganization { People = people, Organization = org, Details = "details" };
      
      peopleRepository.Add(people);          // Just ONE ISession.Save(people)
      
      unitOfWork.Commit();                   // ITransaction.Commit()
      

      非常感谢任何输入。

      由于

1 个答案:

答案 0 :(得分:1)

首先,您需要将新创建的PeopleOrganization添加到两个实体(OrganizationPeople)的集合中。然后,如果您向Cascade.All()链添加HasMany,则保存应向下传播(级联)到PeopleOrganization,然后传播到Organization

作为纯粹的语义建议,我建议将PeopleOrganization创建封装到Person上的方法中。像这样:

class Person
{
  public void AddOrganization(Organization org, string details)
  {
    var link = new PeopleOrganization { ... };

    LinkToOrganization.Add(link)
    org.LinkToPeople.Add(link);
  }
}

这样你就不必自己处理创建内在实体。