2013-04-07 164 views
0

我目前正在處理我的第一個NHibernate項目。NHibernate,通過父母添加孩子vs設置對孩子父母的引用

爲了測試它,我構建了一個實體圖,並且我試圖堅持數據庫。當我通過在IList中插入附加增加孩子的父母沒有在數據庫中工作,因爲我得到的數據庫空列例外(代碼片段)

  1. 當我設置對孩子的參考?這是工作(雖然這種感覺不自然,我父,見代碼片斷
  2. 這是正常的行爲,還是我做錯了什麼

片段1:

var country = new Country(); 
var countryLocale = new CountryLocale { LangCode = "nl-nl", Name = "Nederland" }; 
country.CountryLocales.Add(countryLocale); 

var city = new City(); 
var cityLocale = new CityLocale { LangCode = "nl-nl", Name = "Amsterdam" }; 
city.CityLocales.Add(cityLocale); 
country.Cities.Add(city); 

片段1個錯誤:

Cannot insert the value NULL into column 'CountryId', table 'ArtWorld.dbo.City'; column does not allow nulls. INSERT fails.\r\nThe statement has been terminated.

片段2:

var country = new Country(); 

var countryLocale = new CountryLocale { Country = country,LangCode = "nl-nl", 
             Name = "Nederland" }; 
var city = new City{Country = country}; 

var cityLocale = new CityLocale { City = city, LangCode = "nl-nl", 
             Name = "Amsterdam" }; 

session.SaveOrUpdate(country); 

市和CityLocale地圖:

public class CityMap : ClassMap<City> 
{ 
    public CityMap() 
    { 
     Table("City"); 
     Id(x => x.Id); 
     References(x => x.Country).Column("CountryId").Cascade.SaveUpdate(); 
     HasMany(x => x.CityLocales).KeyColumn("CityId").Cascade.SaveUpdate(); 
    } 
} 

public class CityLocaleMap : ClassMap<CityLocale> 
{ 
    public CityLocaleMap() 
    { 
     Table("City_Locale"); 
     Id(x => x.Id); 
     Map(x => x.LangCode).Not.Nullable(); 
     Map(x => x.Name).Not.Nullable(); 
     References(x => x.City).Column("CityId").Cascade.SaveUpdate(); 
    } 
} 

這是我的國家/ Countrylocale地圖:

public class CountryMap : ClassMap<Country> 
{ 
    public CountryMap() 
    { 
     Table("Country"); 
     Id(x => x.Id); 
     HasMany(x => x.Cities).KeyColumn("CountryId").Cascade.SaveUpdate(); 
     HasMany(x => x.CountryLocales).KeyColumn("CountryId").Cascade.SaveUpdate(); 
    } 

} 

public class CountryLocaleMap :ClassMap<CountryLocale> 
{ 
    public CountryLocaleMap() 
    { 
     Table("Country_Locale"); 
     Id(x => x.Id); 
     Map(x => x.LangCode).Not.Nullable(); 
     Map(x => x.Name).Not.Nullable(); 
     References(x => x.Country).Column("CountryId").Cascade.SaveUpdate(); 
    } 
} 

回答

3

NHibernate的映射更改:

Country方面,你有

HasMany(x => x.CountryLocales).KeyColumn("CountryId").Cascade.SaveUpdate() 

在CountryLocale方面,你有

References(x => x.Country).Column("CountryId").Cascade.SaveUpdate(); 

其中的關係應該註明使用.Inverse()逆。

.Cascase.SaveUpdate()可以確保NHibernate的管理子實體CountryLocale的生命週期,當一個短暫的孩子加入到CountryLocalesCountry的名單。如果您不想明確處理CountryLocale的生命週期,我建議將CountryLocale - >Country中的多對一標記爲Inverse

有兩種方法,你可以讓您在CountryLocale引用Country眼睛酸澀的 intutive

如果國家管理區域設置

Country添加的方法它將管理正在添加的Locale。客戶端(的CountryCountryLocale用戶不必明確地引用玩)

public virtual bool AddCountryLocales(CountryLocale locale) 
{ 
     if(!this.CountryLocales.Contains(locale)) 
     { 
       locale.Country =this; 
       this.CountryLocales.Add(locale); 
       return true; 
     } 
     return false; 
} 

CountryLocale較爲領域驅動

通過重新定義它,這樣你不能有一個CountryLocale沒有Country

public class CountryLocale 
{ 
    public CountryLocale(Country country) 
    { 
     this.Country = country; 
    } 

    //you need a no-agrument constructor for NHibernate 
    protected CountryLocale() 
    { 
    } 
} 
+0

謝謝您的廣泛答覆。這對我幫助很大。 – Patrick 2013-04-07 13:58:00