2009-12-11 86 views
0

NHibernate的新手。无法绕过如何映射这张遗留表格的问题。如何用NHibernate(Fluent)映射这个遗留表?

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

还有,我已经映射到一个人的班集体“CmnPerson”表。我需要Person类包含地址列表,其中objectType列包含“CmnPerson”,而objectId字段与我的Person.Id(“CmnPerson.personId”)字段匹配。

我也稍后将不得不创建一个Contact类,该类还包含objectType列包含“CmnContact”的地址列表。

我有一个非常艰难的时间搞清楚,如果我应该使用任何映射或类层次结构的每个表与子列的歧视?或者如果其中任何一个甚至可以满足我的需求。

任何人都可以显示我如何映射此地址类吗?流利的配置将是可取的。

ADDED信息:

以下类和映射差不多的工作,但地址列表从CmnAddress表匹配的对象ID返回所有行,而不管对象类型字段的值。我想我可以在Person.Addresses的HasMany映射上使用ApplyFilter,但这看起来不像“正确”的方式。

更多的附加信息:我能够通过调用DiscriminateSubClassesOnColumn(...)

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

回答

1

如果Any-mapping的关系很多,则不能使用Any-mapping。当地址可以指向不同种类的对象时,可以使用它 - 例如人员,订单或其他不相关的事物。

要映射hierarachy你可以做这样的:

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映射的集合。你应该完成。

+0

刚才我刚刚提到了这个完全相同的答案 - 只是完成了测试。 它编译并运行,但Person.Addresses列表返回CmnAddress表中所有具有匹配id值的行,而不管区分列中的值如何。 任何想法如何解决? – 2009-12-11 18:23:28

+0

答案是在DiscriminateSubClassesOnColumn(...)调用之后链接AlwaysSelectWithValue()调用。或者至少它似乎有理想的结果。 – 2009-12-11 18:55:27

+1

对不起,我迟到的回复。这很奇怪。我只是用你的场景进行了一次测试,并且我没有必要指定AlwaysSelectWithValue()。 – asgerhallas 2009-12-14 18:23:16

0

地址下课后上链AlwaysSelectWithValue()来解决这最后一个问题

public class Address 
{ 
    public virtual int Id { get; set; } 
    public virtual Person Person { get; set; } 
    // etc. 
} 

Person class

public class Person 
{ 
    public Person() 
    { 
     Addresses = new List<Address>(); 
    } 

    public virtual int Id { get; set; } 
    // etc. 
    public virtual IList<Address> Addresses { get; set; } 
} 

AddressM AP

public class AddressMap : ClassMap<Address> 
{ 
    public AddressMap() 
    { 
     Table("CmnAddress"); 
     Id(x => x.Id).Column("addressId"); 
     // etc. 
     References(x => x.Person); 
    } 
} 

为了区分地址=> Person和Address之间的差异=>联系人,你要对NHibernate的多态性读取并识别基于列的子类。

+0

其歧视部分我有麻烦理解。 我不确定是否需要制作从地址继承的子类 - 如PersonsAddress和ContactsAddress。我也没有完全清楚将字符串“CmnPerson”和“CmnContact”映射到适当的Address子类的Fluent方法。 – 2009-12-11 15:30:12

1

对不起,我不熟悉流利的映射,但是,这样做的一种方式将是:

  • 对应于所有列的属性在表中除了的objectType创建地址抽象类
  • 创建PersonAddress类延伸地址
  • 创建一个ContactAddress类延伸地址

  • 地图所有CmnAddress列以正常方式地址类的属性,除了其声明作为鉴别列的objectType

  • 地图PersonAddress作为的子类别地址具有鉴别器值“CmnPerson”
  • 地图ContactAddress地址与“CmnContact”的鉴别值

在代码中的子类,你的Person类将持有的PersonAddresses名单和联系类将持有的列表ContactAddresses

相关问题