Fluent nHibernateでの基本クラスのリストの保存
-
05-07-2019 - |
質問
私は少し流FluなnHibernate初心者なので、これは簡単であり、見逃しているだけです。
Personを継承するCustomerとUserのクラス階層があります。顧客とユーザーはそれぞれ独自のテーブルとマッピングを持ち、すべてがうまく機能しています。
私の問題は、顧客とユーザーが連絡先のリストを持っている必要があることです。連絡先はIList型になります。そのため、顧客とユーザーはそれぞれ、顧客とユーザーの混合を含むことができる連絡先のリストを持ちます。
これをどのようにマッピングするかに困惑しており、提供されているアドバイスをいただければ幸いです。
ありがとう!
解決
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; }
}
あなたの問題を解決する簡単な(ハックな)方法は、識別者であり、すべてを同じテーブルに移動します。このマッピングは次のようになります。
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>
が必要な場合に、選択したPersonが実際にどのサブクラスであるかを判断する方法を理解する必要がありますが、それを理解できると確信しています。 :)これがお役に立てば幸いです!
他のヒント
これは、パーティモデルごとに行いました。このように、抽象化は常にパーティーです:
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; }
}
}
マッピングには、2つの可能な戦略があります。継承ツリーごとに1つのテーブル。クラスごとに1つのテーブル。
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);
}
}
これにより、Party、Person、Organization、Contactの4つのテーブルが作成されます