2011-01-11 3 views
1

をスロー保存し、その後削除、保存は、私のテストケースである:NHibernateは:同じエンティティがここStaleStateException

[Test, Explicit] 
public void SaveDeleteSaveThrowsTest() 
{ 
    Produit produit = new Produit { Libelle = "Test" }; 

    using (ISession session = this.SessionProvider.OpenSession()) 
    { 
     session.FlushMode = FlushMode.Auto; 

     using (ITransaction transaction = session.BeginTransaction()) 
     {      
      session.SaveOrUpdate(produit); 
      transaction.Commit(); 
     } 

     using (ITransaction transaction = session.BeginTransaction()) 
     { 
      session.Delete(produit); 
      transaction.Commit(); 
     } 

     using (ITransaction transaction = session.BeginTransaction()) 
     { 
      session.SaveOrUpdate(produit); 
      Assert.Throws(typeof(StaleStateException), transaction.Commit); 
     } 
    } 
} 

Idsがハイローによって生成されます。

2回目に保存する前にエンティティのIDに0を代入すると、この単純なケースでは機能しますが、1対多の関係を持つより複雑なシナリオでは機能しません(例外は「コレクション親エンティティを削除しようとしたときに「セッションに関連付けられていない所有者」)。

これを機能させる方法はありますか? (同じエンティティを再度保存して保存しないでください)

+0

削除後に保存しようとしているのはなぜですか? – UpTheCreek

+0

これはWPFアプリケーションであり、画面ごとにセッションを使用しています。このエンティティはデータグリッドで使用され、チェックボックスをオフにするとチェックボックスが削除されます。私はまだそれがデータベースから削除された後にバインディングのためにそれが必要です。ユーザーが再度チェックして「保存」ボタンを押すと、データベースに再保存されます。 –

+0

柔らかい削除のようなサウンドはそれをよりきれいにするでしょう。 – UpTheCreek

答えて

0

削除されたproducerオブジェクトをSession.SaveまたはSession.Lockを呼び出してみてください。

ただし、最初にこの問題を回避するためにデザインを再考する必要があります。別のコレクションで削除するIDを追跡し、トランザクションがコミットされたときに削除を実行します。

2

多対多関係で遅延読み込みを使用しないでください。 問題は、最初にエンティティをロードしてセッションを終了し、(すでにデタッチされた)エンティティで操作しようとしていることです。このような場合、サブエンティティは閉鎖セッションに接続されたプロキシです。 NHibernateにプロキシを再初期化するように指示する必要があります:各サブエンティティに対してNHibernateUtil.Initializeを呼び出します。

1

SaveOrUpdateの代わりにMergeを試してください。データベース内のレコードを検索します(挿入または更新する前に追加選択します)。 Mergeには、指定されたインスタンスが依然として一時的である間に永続インスタンスを返す戻り値があることに注意してください。動作させるには、セッションを消去するか、新しいセッションを作成する必要があります。