【问题标题】:Fluent Nhibernate many-to-many issueFluent Nhibernate 多对多问题
【发布时间】:2010-12-15 17:05:39
【问题描述】:

我有三张桌子:

  1. 人员(ID、名字)
  2. 组织(ID、名称)
  3. PersonOrganization(PersonId、OrganizationId、Details)多对多表

当我第一次使用 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. 是否有办法让我能够执行以下操作(这将写入所有三个表):

-

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()

非常感谢您的任何意见。

谢谢

【问题讨论】:

    标签: nhibernate fluent-nhibernate nhibernate-mapping


    【解决方案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);
      }
    }
    

    这样您就不必自己创建内部实体了。

    【讨论】:

    • 詹姆斯,感谢您的意见。当我将 PeopleOgranization 添加到两个实体的集合并将 Cascade.All 添加到两个 HasMany 链时,我得到以下异常:对象引用了未保存的瞬态实例 - 在刷新之前保存瞬态实例。知道为什么吗?
    • 某些东西没有被级联。我会冒险猜测并说这是您的 PeopleOrganization 实体上的 PersonOrganization 属性;保存是从Person 级联的,但不是从PeopleOrganizationOrganization。尝试在PeopleOrganization 的映射中为这些属性添加级联。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-07-17
    • 1970-01-01
    • 2011-10-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-16
    相关资源
    最近更新 更多