2009-12-11 88 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

相關問題