Сохранение списка базовых классов в Fluent nHibernate - PullRequest
1 голос
/ 27 ноября 2009

Я немного новичок в беглом nHibernate, так что простите, это легко, и я просто скучаю по нему.

У меня есть иерархия классов с Customer и User, которые оба наследуются от Person. У каждого клиента и пользователя есть своя таблица и отображение, и все работает отлично.

Моя проблема в том, что у Клиента и Пользователя должен быть список контактов, который будет иметь тип IList. Поэтому у Клиента и Пользователей будет список контактов, который может содержать сочетание Клиентов и Пользователей.

Я немного озадачен тем, как это отобразить, и буду признателен за любой совет, который предлагается.

Спасибо!

Ответы [ 2 ]

1 голос
/ 27 ноября 2009

Я считаю, что вам нужен IList<Person> Contacts {get;set;} и тип (дискриминатор), чтобы вы знали, к чему его привести. Может быть, это хак, но я бы так и сделал.

EDIT: Допустим, ваши сущности будут выглядеть следующим образом.

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

Простой (хакерский) способ решения вашей проблемы - дискриминатор и перемещение всего на один стол. Сопоставление для этого может выглядеть следующим образом:

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>, но я уверен, что вы можете это выяснить. :) Надеюсь, это поможет!

0 голосов
/ 28 ноября 2009

Я сделал это по модели партии. Таким образом, ваша абстракция всегда вечеринка:

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 таблицы: Партия, Персона, Организация и Контакт

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...