2

私は現在、最初の NHibernate プロジェクトに取り組んでいます。

それをテストするために、エンティティ グラフを作成しており、そのグラフをデータベースに永続化しようとしています。IList の追加を介して親に子を追加すると、データベースで null 列の例外が発生するため、データベースで挿入が機能しません (コード スニペット 1)

  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 エラー:

値 NULL を列 'CountryId'、テーブル 'ArtWorld.dbo.City' に挿入できません。列はヌルを許可しません。INSERT が失敗しました。\r\nステートメントは終了しました。

スニペット 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);

都市と都市ロケール マップ:

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

これは私の国/国のロケールマップです:

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();
    }
}
4

1 に答える 1

4

Hibernate マッピングの変更:

あなたが持っているCountry側に

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

あなたが持っているCountryLocale側で

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

関係の 1 つは、 を使用して逆としてマークする必要があります.Inverse()

は、一時的な子が親の のリストに追加されたときに.Cascase.SaveUpdate()、NHibernate が子エンティティのライフサイクルを確実に管理するようにします。CountryLocale のライフ サイクルを自分で明示的に処理したくない場合は、多対 1 側を from -> as としてマークすることをお勧めします。CountryLocaleCountryCountryLocalesCountryLocaleCountryInverse

参照Country不機嫌CountryLocaleにならず、より直感的にする方法が 2 つあります。

国がロケールを管理する場合

Country追加されるロケールを管理するメソッドを追加します。クライアント (のユーザーでCountryありCountryLocale、参照を明示的に操作する必要はありません)

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

CountryLocale はよりドメイン駆動型です

CountryLocaleaなしでは a を持てないように再定義することにより、Country

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

    //you need a no-agrument constructor for NHibernate
    protected CountryLocale()
    {
    }
}
于 2013-04-07T13:23:51.650 に答える