2

私は NHibernate プロジェクトに取り組んでおり、以前はコレクションの読み込みに問題がありました (http://stackoverflow.com/questions/4213506/c-hibernate-criteria-loading-collection)、現在はデータの使用に問題があります。

C# を NHibernate および Spring.Net フレームワークと組み合わせて使用​​しています。たとえば、「ordercredit」をロードしてから ordercredit のオブジェクトにアクセスすると、LazyInitializationException が発生します。

OrderCredit を取得するには、次のコードを使用します。

OrderCredit oc = CreditService.getOrderCredit(ordercredit.Id);

読み込みに使用するコードは、DAO 実装を使用して行われます。

[Transaction(TransactionPropagation.Required, ReadOnly = true)]
public OrderCredit GetOrderCredit(long ordercreditid)
{
    var creditrules = Session.CreateCriteria(typeof(OrderCredit));
    creditrules.Add(Restrictions.Eq("Id", ordercreditid));
    return creditrules.List<OrderCredit>()[0];
}

これをローカル マシンで実行すると、すべて正常に動作し、実際には「ordercredits」のリストをロードするつもりでしたが、これもうまくいかなかったので、最初に簡単な手順を試しました。

「OrderCredit」内のオブジェクトは [OneToMany] として定義されます。

これをテストサーバーに配置し、ロードされた OrderCredit の「OrderObject」オブジェクトにアクセスしようとすると、エラーが発生します。

NHibernate.LazyInitializationException: Initializing[.OrderObject#5496522]-プロキシを初期化できませんでした - セッションがありません。

失敗するコード:

Log.Debug(oc.OrderObject.Name);

動作するコード:

Log.Debug(oc.Id);

これは、OrderCredit の一部であるすべてのオブジェクトで発生しますが、OrderCredit のプロパティ フィールド (たとえば、OrderCredit.Id) にアクセスできます。

また、メソッドを呼び出す元の関数にデータを返す前にオブジェクトにアクセスすると、情報にアクセスできるため、情報がキャッシュされます。

Lazyをオフにするなど、この問題について多くのことを読みましたが、それもうまくいきませんでした(または、間違った場所でそれを行いました)。

私を最も苛立たせているのは、テストサーバーではなく、ローカル マシンで実際に動作するという事実です。私は何が間違っているのでしょうか?

どんな助けでも大歓迎です。

最初の更新:

私は現在 GenericDao を使用しており、1 ordercredit をロードするデフォルトの方法を使用しています。次のコードを使用して、ID ごとに 1 つの ordercredit をロードします。

OrderCredit oc = GenericService.Load<OrderCredit>(Id);

GenericDAO 内のコードは次のとおりですが、セッションを終了または中断することはありません。つまり、ordercredit に関連付けられたオブジェクトにアクセスできます。

[Transaction(TransactionPropagation.Supports, ReadOnly = true)]
public T Load<T>(long id) where T : ISaveableObject
{
    var obj = Session.Load<T>(id);
    return obj;
}

これは、この質問の前半に含めた関数のコードとほぼ同じです。

何が原因でセッションが終了するのかわからないので、今は本当に混乱しています。動作するように今は作業しますが、後で変更したいので、関数を使用してコレクション全体を呼び出し、for each ループ経由でアクセスできるようにします。

現在、「getOrderCredits」関数を使用して OrderCredit オブジェクトのリストを取得し、foreach で Id を取得し、GenericDao.Load を使用して実際のアイテムを取得し、オブジェクトなどにアクセスできます。もちろん、これはあるべき姿ではなく、そうあるべきです。

これが解けたらビックリです。

4

1 に答える 1

4

これは、NHibernate を使用するときによくある問題です。次の理由で発生します。

  1. セッションを開く
  2. 別のエンティティを参照するデータベースからエンティティをロードします
  3. セッションを閉じます
  4. 参照エンティティのプロパティにアクセスしようとしています
  5. NHibernate は、親エンティティをロードしたのと同じセッションを使用して、データベースからエンティティを遅延ロードしようとします。
  6. セッションが閉じられているため、NHibernate は woah のような例外をスローします。

ここにはいくつかのオプションがあります。

  1. できれば作業単位パターンなどを使用して、セッションをより長く開いたままにしてください。これにより、より厳密に制御できます。
  2. クエリを実行するときに、参照されているエンティティを積極的に読み込みます。

あなたの場合、Spring がトランザクションを管理しているため、2 番目のオプションがおそらく最も迅速で簡単なソリューションです。

var creditrules = Session.CreateCriteria(typeof(OrderCredit));
creditrules.Add(Restrictions.Eq("Id", ordercreditid))
  .SetFetchMode("OrderObject", FetchMode.Eager);

これにより、 をロードするOrderObjectときに がロードされますOrderCredit

于 2011-03-02T21:10:38.153 に答える