保存Fluent nHibernate中的基类列表

时间:2009-11-27 01:27:53

标签: fluent-nhibernate

我是一个流利的nHibernate新手,所以原谅我这很容易,我只是错过了它。

我有一个Customer和User的类层次结构,它们都继承自Person。客户和用户都有自己的表和映射,一切都很好。

我的问题是客户和用户需要有一个联系人列表,其类型为IList。因此,客户和用户都将拥有一个可以包含客户和用户组合的联系人列表。

我对如何映射这一点感到有点难过,并希望得到任何建议。

谢谢!

2 个答案:

答案 0 :(得分:1)

我相信你需要一个IList<Person> Contacts {get;set;}和一个类型(鉴别器),以便你知道要把它投射到什么。也许这是一个黑客,但我就是这样做的。

编辑: 假设您的实体如下所示。

public abstract class Person
{
    public virtual int Id { get; private set; }
    public virtual string FirstName { get; set; }
    public virtual string LastName { get; set; }
}

public class Customer : Person
{
    public virtual string Foo { get; set; }
}

public class Contact : Person
{
    public virtual string Bar { get; set; }
}

解决问题的简单方法(hacky)将是一个鉴别器,并将所有内容移动到同一个表中。此映射可能如下所示:

public class PersonMap : ClassMap<Person>
{
    public PersonMap()
    {
        Id(x => x.Id).GeneratedBy.Native();
        Map(x => x.FirstName).Length(40);
        Map(x => x.LastName).Length(100);
        DiscriminateSubClassesOnColumn("TypeOfPerson");
    }
}

public class CustomerMap : SubclassMap<Customer>
{
    public CustomerMap()
    {
        Map(x => x.Foo);
    }
}

public class ContactMap : SubclassMap<Contact>
{
    public ContactMap()
    {
        Map(x => x.Bar);
    }
}

如果您根据该模型生成架构,最终会得到:

create table [Person] (
  Id                 INT   IDENTITY   NOT NULL,
  BillingDetailsType NVARCHAR(255)   not null,
  FirstName          NVARCHAR(40)   null,
  LastName           NVARCHAR(100)   null,
  Foo                NVARCHAR(255)   null,
  Bar                NVARCHAR(255)   null,
    primary key ( Id ))

我确实理解这可能并不理想,所以如果你的老板(像我的)是一个拒绝让数据库处于这种状态的数据库专家。您需要做的就是删除DiscriminateSubClassesOnColumn("TypeOfPerson");,如果您从代码中生成架构,则应该最终得到如下所示的表结构:

-- statement #1
create table [Person] (
  Id        INT   IDENTITY   NOT NULL,
  FirstName NVARCHAR(40)   null,
  LastName  NVARCHAR(100)   null,
    primary key ( Id ))

-- statement #2
create table [Customer] (
  Person_id INT   not null,
  Foo       NVARCHAR(255)   null,
    primary key ( Person_id ))

-- statement #3
create table [Contact] (
  Person_id INT   not null,
  Bar       NVARCHAR(255)   null,
    primary key ( Person_id ))

-- statement #4
alter table [Customer]
 add constraint FKFE9A39C0B58BA2A5 foreign key ( Person_id ) references [Person]

使用这个最后一个模式,你需要找到一种方法来确定所选人员的真正所在的子类,如果你需要一个IList<Person>,但我相信你可以解决这个问题。 :)希望这有帮助!

答案 1 :(得分:0)

我是通过Party模型完成的。这样你的抽象总是派对:

public abstract class Party
{
     private IList<Party> _contacts = new List<Party>();

     public int Id {get; set;}
     public abstract string DisplayName { get; }
     public IEnumerable<Party> Contacts { get { return _contacts; } }  
}

public class Person 
{
     public string FirstName {get; set;}
     public string LastName {get; set;}

     public override string DisplayName 
     {
         get { return FirstName + " " + LastName; }
     }
}

public class Organization
{
     public string Name {get; set;}

     public override string DisplayName 
     {
         get { return Name; }
     }
}

对于映射,有两种可能的策略:每个继承树有一个表;每班一张桌子。

public class PartyMap : ClassMap<Party>
{
    public PartyMap()
    {
        Id(x => x.Id).GeneratedBy.Native();
        HasManyToMany(x => x.Contacts).Access.CamelCaseField(Prefix.Underscore);
    }
}

public class PersonMap : JoinedSubClassPart<Person>
{
    public PersonMap()
    {
        Map(x => x.FirstName).Length(40);
        Map(x => x.LastName).Length(100);
    }
}

public class OrganizationMap : JoinedSubClassPart<Organization>
{
    public OrganizationMap()
    {
        Map(x => x.Name).Length(40);
    }
}

这应创建4个表:派对,人员,组织和联系