在 Fluent nHibernate 中保存基类列表

发布于 2024-08-12 05:12:48 字数 254 浏览 2 评论 0原文

我是一个 Fluent nHibernate 新手,所以请原谅我,这很简单,但我只是想念它。

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

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

我对如何绘制此图感到有点困惑,并且非常感谢您提供的任何建议。

谢谢!

I'm a bit of a Fluent nHibernate newbie, so forgive me is this is easy and I'm just missing it.

I have a class hierarchy with Customer and User which both inherit from Person. Customer and User each have their own table and mapping and everything is working great.

My problem is that Customer and User need to have a list of Contacts, which will be of type IList. So Customer and Users will each have a list of contact that can contain a mix of Customers and Users.

I'm kinda stumped on how to map this and would appreciate any advice that is offered.

Thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

暮凉 2024-08-19 05:12:49

我相信您需要一个 IList联系 {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 到底是哪个子类,但我相信您可以弄清楚。 :) 希望这有帮助!

I believe you need a IList<Person> Contacts {get;set;} and a type (discriminator) so that you know what to cast it to. Maybe it's a hack but that's how I would do it.

EDIT:
Let's say your entities would look like below.

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; }
}

The easy (hacky) way of solving your problem would be a discriminator and move everything to the same table. The mapping for this could look like:

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);
    }
}

If you generate your schema based on that model you end up with:

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

I do understand that this is maybe not ideal certainly so if your boss (like mine) is a database guru that refuses to leave the database in such a state. All you need to do then is to remove the DiscriminateSubClassesOnColumn("TypeOfPerson"); and you should instead end up with a table structure like below should you generate the schema from your code:

-- 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]

With this last schema you need to figure out a way to determine which subclass the selected Person really is if you ever need an IList<Person> but I am sure you can figure that out. :) Hope this helps!

魔法唧唧 2024-08-19 05:12:49

我是按照党的模式做到这一点的。这样,您的抽象始终是 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 个表:Party、Person、Organization 和 Contact

I have done this by Party model. This way your abstraction is always 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; }
     }
}

For mapping there are two possible strategies: One table per inheritance tree; one table per class.

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);
    }
}

That should create 4 tables: Party, Person, Organization and Contact

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文