私のドメインはいくつかの端末を含む空港であり、各端末にはゾーンなどが含まれています。
空港/端末/ゾーンエンティティの数は非常に少ないので、
1.空港を検索するときに、すべての階層を熱心に読み込みます。
:空港オブジェクトのすべての回収のは、DBヒットないように(以下流暢構成を使用
nHibernate eager load-strange updateの動作
//eagerly load terminals
mapping.HasMany(x => x.Terminals).Not.LazyLoad()
.Cache.ReadWrite();
)
2は、第2レベルのキャッシュを有効にします。
熱心な読み込みとキャッシュがうまくいきますが、次のテストでは奇妙な動作が発生します。
(。次のコードは、空港エンティティそれらの二倍(DBをもう一度叩いていない)、及びアップデートいずれかを取得)
[TestMethod]
public void TestSecondLevelCache()
{
Airport firstAirport = null, secondAirport = null;
Console.WriteLine("first select");
using (ISession session = this.SessionFactory.OpenSession())
{
using (ITransaction transaction = session.BeginTransaction())
{
//the idea here is to see whether there are two calls to DB here. check the sql output
AirportDAO dao = new AirportDAO(session);
firstAirport = dao.GetAirport();
transaction.Commit();
}
}
Console.WriteLine("second select");
using (ISession session = this.SessionFactory.OpenSession())
{
using (ITransaction transaction = session.BeginTransaction())
{
//the idea here is to see whether there are two calls to DB here. check the sql output
AirportDAO dao = new AirportDAO(session);
secondAirport = dao.GetAirport();
transaction.Commit();
}
}
Console.WriteLine("Are those the same airport instance? " + firstAirport.Equals(secondAirport));
Console.WriteLine("now adding a terminal");
using (ISession session = this.SessionFactory.OpenSession())
{
using (ITransaction transaction = session.BeginTransaction())
{
secondAirport.Terminals.Add(new Terminal() { Name = "terminal added to second airport", Zones = new List<Zone>() });
session.Update(secondAirport);
transaction.Commit();
}
}
//this Assert fails, since firstAirport != secondAirport
Assert.IsNotNull(firstAirport.Terminals.FirstOrDefault(t => t.Name.Contains("second airport")));
}
は、結果の出力を参照してください
第一選択します。
NHibernateは:DBO FROM IsDeleted36_0_としてId36_0_、Name36_0_としてairport0_.Name、airport0_.IsDeletedとしてairport0_.Idを[空港] airport0_ [email protected]; @ P0 = 1
NHibernateは:SEターミナル0_.Airport_idとしてAirport4_1_、ターミナル0_.IdとしてId1_、ターミナル0_.IdとしてId50_0_、ターミナル0_.NameとしてName50_0_、ターミナル0_.IsDeleted50_0_、ターミナル0_.Airport_idとしてAirport4_50_0_からdbo。[ターミナル] terminals0_ WHERE [email protected] ; @ P0 = 1
NHibernateは:DBO FROM Terminal4_51_0_としてTerminal4_1_、Id1_としてzones0_.Id、Id51_0_としてzones0_.Id、Name51_0_としてzones0_.Name、IsDeleted51_0_としてzones0_.IsDeleted、zones0_.Terminal_idとしてzones0_.Terminal_idを[ゾーン] zones0_ [email protected];それらは同じ空港インスタンス@ P0 = 2
二
を選択していますか?偽
今端末
NHibernateの追加:(UPDLOCK、ROWLOCK)でdbo._uniqueKeyからnext_hi選択
NHibernateは:更新dbo._uniqueKey設定next_hi = @ P0ここnext_hi = @ P1; @ P0 = 17、@ @ p0 = 16
[Terminal](名前、IsDeleted、Airport_id、Id)VALUES(@ p0、@ p1、@ p2、@ p3); @ p0 = '第2の空港に端末が追加されました' @ p1 = False、@ p2 = NULL、@ p3 = 16
NHibernate:UPDATE dbo。[Airport] SET名= @ p0、IsDeleted = @ p1 WHERE Id = @ p2; @ p0 = 'テスト空港'、@ p1 = False、@ p2 = 1
NHibernate:UPDATE dbo。[T @ p1 = False、@ p2 = 1、@ p3 = 2
NHibernate:@ p1 = False、@ p0 = UPDATE dbo。[ゾーン] SET Name = @ p0、IsDeleted = @ p1、Terminal_id = @ p2 WHERE Id = @ p3; @ p0 = 'テストゾーン'、@ p1 = False、@ p2 = 2、@ p3 = 3
NHibernate:UPDATE dbo。[ターミナル] SET Airport_id = @ P0 ID = @ P1; @ P0 = 1、@ P1 = 16
私の問題は、次のとおりです。
1.すべてを更新奇妙な更新動作.. 。
2. firstAirportとsecondAirportが同じオブジェクトではないという事実(多分私は第二レベルのキャッシュについての何かが欠けてるの?)事前に
おかげで、
ジョニー
ありがとうございます!それはうまくいくようです。 また、firstAirport!= secondAirportについて、私の目的は、あるセッションが空港を更新したときに、他のセッションが直ちに(Get()を呼び出さずに)それを見るかどうかを確認することでした。私は今これがかなりばかげた仮定であることを知っています。明らかに、別のセッションによってオブジェクトに加えられた変更を見たい場合は、そのオブジェクトを再度ロードする必要があります。 –
また、Merge()を使用してAyendeのソリューションをチェックしてください - http://ayende.com/Blog/archive/2009/11/08/nhibernate-ndash-cross-session-operations.aspx –