私は、NHibernate を使用して適度に負荷の高いデータ処理を行っているコードに取り組んでいます (はい、私は知っていますが、おそらくその仕事に適したツールではないかもしれません。しかし、それは私が使用しなければならないものです)
ステートレス セッションを使用して最初の 1000 個のオブジェクトを取得し、必要に応じてそれらをチェック、更新し、更新されたオブジェクトのリストに追加します。完了するまで、次の 1000 個のオブジェクトに対して繰り返します。以下は、大幅に簡略化されたバージョンのコードです。
List<MarketOrder> updated = new List<MarketOrder>();
IStatelessSession session = SessionProvider();
int offset = 0;
bool moreToGet = true;
while (moreToGet)
{
var result = session.Query<MarketOrder>().Where(o => o.Owner.ID == currentEntityID && !o.Updated);
var tmp = result.Skip(offset).Take(1000);
foreach (MarketOrder item in data)
{
notUpdated.OrderState = MarketOrderState.Closed;
updated.Add(notUpdated);
}
if (data.Count == pageSize) { offset += pageSize; }
else { moreToGet = false; }
}
次に、別のステートレス セッションを開いて一括更新を行います。
IStatelessSession session = SessionProvider();
foreach (MarketOrder o in updated) { session.Update(o); }
単体テストを実行すると、次のエラーが表示されます。
Test 'TestProcess_AutoCloseOrder' failed: NHibernate.PropertyValueException : Error dehydrating property value for Data.Models.MarketOrder.Owner
---- NHibernate.PropertyAccessException : Exception occurred getter of Common.Models.ModelBase.Version
-------- System.Reflection.TargetInvocationException : Exception has been thrown by the target of an invocation.
------------ NHibernate.SessionException : proxies cannot be fetched by a stateless session
いろいろいじった後、更新でNHibernateが保存されOwner
ているプロパティにアクセスしようとしていることがエラーの原因であることがわかりました。MarketOrder
(これは更新をカスケードするためだと思います)に
Owner
はプロキシが設定されており、ステートレスセッションからロードされたため、アクセスできません。
案の定、ステートレス セッションではなく通常のセッションからロードすると、すべて正常に動作します。ただし、このソリューションは本番環境でパフォーマンスに影響を与えるため、避けたいと思います。
Owner
遅延ロードしないように設定することもできますが、それはすべての同様のケースに対する実用的な解決策ではありません。
この質問に対する答え: NHibernate: proxies cannot be fetched by a stateless session error message . 初期ロードの一部として問題のあるプロパティを取得することを提案していますが、それは非常に無駄に思えます。メイン オブジェクトのいくつかのプロパティだけを更新したいのですが、そのオブジェクトのすべての子参照もロードする必要があるのはなぜですか?
私が望むのは、NHibernate がメインMarketOrder
オブジェクトのみが変更されたことを認識し、わざわざ更新を にカスケードする必要がないことOwner
です。実際、今考えてみると、Stateless Session が更新をカスケードすることになっているとはまったく思いませんでしたか?
ここで何が起こっているのか、どうすれば解決できるのか誰か知っていますか?