NHibernate新手。无法解决如何映射此旧表的问题。
CREATE TABLE [dbo].[CmnAddress](
[addressId] [int] NOT NULL,
[objectType] [varchar](63) NULL,
[objectId] [int] NULL,
[addressType] [varchar](7) NULL,
[recordStatus] [char](1) NULL,
[fromDate] [int] NULL,
[toDate] [int] NULL,
[onStreet] [varchar](254) NULL,
[atStreet] [varchar](254) NULL,
[unit] [varchar](30) NULL,
[city] [varchar](254) NULL,
[state] [varchar](30) NULL,
[zipCode] [varchar](30) NULL,
)
还有一个我已映射到Person类的“CmnPerson”表。我需要Person类包含一个Addresses列表,其中objectType列包含“CmnPerson”,objectId字段与我的Person.Id(“CmnPerson.personId”)字段匹配。
我后来还要创建一个Contact类,它还包含一个地址列表,其中objectType列包含“CmnContact”。
我很难搞清楚我是否应该使用Any映射或每个类的class-hierarchy对子列进行区分?或者,如果其中任何一个甚至满足我的需求。
有人能告诉我如何映射这个地址类吗? Fluent配置会更好。
添加信息:
以下类和映射几乎可以工作,但是无论objectType字段的值如何,Addresses列表都会返回CmnAddress表中具有匹配objectId的所有行。我想我可以在Person.Addresses的HasMany映射上使用ApplyFilter,但这似乎不是“正确”的方式。
更多添加信息:通过在调用DiscriminateSubClassesOnColumn(...)之后链接AlwaysSelectWithValue(),我能够解决最后一个问题
public class Person
{
public virtual int Id { get; private set; }
public virtual string LastName { get; set; }
public virtual string FirstName { get; set; }
public virtual string MiddleName { get; set; }
public virtual string Gender { get; set; }
public virtual IList<PassClient> PassClients { get; set; }
public virtual IList<PersonAddress> Addresses { get; set; }
}
public class PersonMap : ClassMap<Person>
{
public PersonMap() {
Table("CmnPerson");
Id(x => x.Id).Column("personId");
Map(x => x.LastName);
Map(x => x.FirstName);
Map(x => x.MiddleName);
Map(x => x.Gender);
HasMany(x => x.PassClients).KeyColumn("personId");
HasMany(x => x.Addresses).KeyColumn("objectId");
}
}
abstract public class Address
{
public virtual int Id { get; private set; }
public virtual string StreetNo { get; set; }
public virtual string OnStreet { get; set; }
public virtual string Unit { get; set; }
public virtual string City { get; set; }
public virtual string State { get; set; }
public virtual string ZipCode { get; set; }
}
public class PersonAddress : Address {
public virtual Person Person { get; set; }
}
public class AddressMap : ClassMap<Address>
{
public AddressMap() {
Table("CmnAddress");
Id(x => x.Id).Column("addressId");
Map(x => x.StreetNo);
Map(x => x.OnStreet);
Map(x => x.Unit);
Map(x => x.City);
Map(x => x.State);
Map(x => x.ZipCode);
DiscriminateSubClassesOnColumn("objectType").AlwaysSelectWithValue();
}
}
public class PersonAddressMap : SubclassMap<PersonAddress>
{
public PersonAddressMap() {
DiscriminatorValue("CmnPerson");
References(x => x.Person).Column("objectId");
}
}
答案 0 :(得分:1)
抱歉,我不熟悉流畅的映射,但是,一种方法是:
创建 ContactAddress 类,其中包含地址
以正常方式将 CmnAddress 的所有列映射到地址类的属性,但声明的 objectType 除外作为鉴别列
在代码中,您的Person类将包含 PersonAddresses 列表,而您的Contact类将包含 ContactAddresses
列表答案 1 :(得分:1)
当它有很多关系时,你不能使用Any-mapping。当地址可以指向不同类型的对象时,可以使用它 - 例如人,订单或其他不相关的东西。
要映射层次结构,您可以这样做:
public class CmnAddressMap : ClassMap<CmnAddress>
{
public CmnAddressMap()
{
Id(x => x.addressId);
Map(x => x...);
DiscriminateSubClassesOnColumn("objectType");
}
}
public class PersonAdressMap : SubclassMap<PersonAddress>
{
public PersonAdressMap()
{
DiscriminatorValue("objectType1");
}
}
public class ContactAdressMap : SubclassMap<ContactAddress>
{
public ContactAdressMap()
{
DiscriminatorValue("objectType2");
}
}
具有包含所有字段的抽象CmnAddress(例如,映射CmnAdressMap中的所有字段)和两个名为PersonAddress和ContactAddress的子类。
然后这个人应该拥有像IList这样的集合,它应该与HasMany映射。你应该完成。
答案 2 :(得分:0)
地址类
public class Address
{
public virtual int Id { get; set; }
public virtual Person Person { get; set; }
// etc.
}
人类
public class Person
{
public Person()
{
Addresses = new List<Address>();
}
public virtual int Id { get; set; }
// etc.
public virtual IList<Address> Addresses { get; set; }
}
AddressMap
public class AddressMap : ClassMap<Address>
{
public AddressMap()
{
Table("CmnAddress");
Id(x => x.Id).Column("addressId");
// etc.
References(x => x.Person);
}
}
分隔地址=&gt;之间的差异人和地址=&gt;联系,您需要阅读NHibernate的多态性并根据列区分子类。