12

すでに存在するかどうかに関係なく、データベースに行を書き込む必要があります。NHibernate を使用する前は、これはストアド プロシージャで行われていました。プロシージャは更新を試行し、行が変更されていない場合は挿入にフォールバックします。アプリケーションはレコードが存在するかどうかを気にしないため、これはうまく機能しました。

私が見つけた NHibernate のソリューションでは、エンティティをロードして変更するか、エンティティを削除して新しいエンティティを挿入できるようにする必要があります。アプリケーションは、レコードが既に存在するかどうかを気にする必要があります。それを回避する方法はありますか?

IDは重要ですか?

割り当てられた ID

オブジェクトには割り当てられた ID としてキーワードがあり、テーブルの主キーです。

SaveOrUpdate() は Id に基づいて Save() または Update() メソッドを適切に呼び出すことを理解しています。割り当てられた ID を使用すると、ID が保存されていない値ではないため、これは機能しません。ただし、代わりに Version または Timestamp フィールドをインジケータとして使用できます。実際には、メモリ内のオブジェクトがデータベース内のレコードに関連付けられているかどうかのみが反映されるため、これは関係ありません。レコードがデータベースに存在するかどうかは示しません。

生成された ID

割り当てられた ID が本当に問題の原因である場合は、キーワードの代わりに生成された ID を主キーとして使用できます。これにより、事実上常に挿入されるため、NHibernate の挿入/更新の問題が回避されます。ただし、キーワードの重複を防ぐ必要があります。キーワード列に一意のインデックスを使用すると、主キーが異なっていても、重複するキーワードに対して例外がスローされます。

別のアプローチ?

おそらく問題は実際には NHibernate にあるのではなく、これがモデル化されている方法にあります。アプリケーションの他の領域とは異なり、これはオブジェクト中心ではなくデータ中心です。NHibernate によって読み書きが簡単になり、ストアド プロシージャが不要になるのは素晴らしいことです。しかし、既存の値に関係なく単純に記述したいという欲求は、オブジェクトのアイデンティティ モデルのモデルにうまく適合しません。これにアプローチするより良い方法はありますか?

4

7 に答える 7

7

使っています

    public IList<T> GetByExample<T>(T exampleInstance)
    {
        return _session.CreateCriteria(typeof(T))
                    .Add(Example.Create(exampleInstance))
                    .List<T>();
    }

    public void InsertOrUpdate<T>(T target)
    {
        ITransaction transaction = _session.BeginTransaction();
        try
        {
            var res=GetByExample<T>(target);
            if( res!=null && res.Count>0 )
                _session.SaveOrUpdate(target);
            else
               _session.Save(target); 
            transaction.Commit();
        }
        catch (Exception)
        {
            transaction.Rollback();
            throw;
        }
        finally
        {
            transaction.Dispose();
        }
    }

しかし、FindByExample メソッドは、正確な ID を持つオブジェクトではなく、すべてのオブジェクトを同様に返します。パラメータとしてオブジェクトしかないため、特定の ID フィールドにアクセスできないため、使用できませんsession.get(Object.class(), id);

于 2009-01-27T08:50:27.727 に答える
6

通常、NHibernate は unsaved-value に依存して、エンティティを挿入するか作成するかを決定できます。ただし、ID を割り当てているため、NHibernate にはエンティティが既に永続化されているように見えます。したがって、オブジェクトのバージョン管理に依存して、それが新しいオブジェクトであることを NHibernate に知らせる必要があります。エンティティをバージョン管理する方法については、次のリンクを参照してください。

http://web.archive.org/web/20090831032934/http://devlicio.us/blogs/mike_nichols/archive/2008/07/29/when-flushing-goes-bad-assigned-ids-in-nhibernate. aspx

于 2009-02-04T22:17:57.210 に答える
0

session.SaveOrUpdate(object) メソッドを使用します。

于 2008-11-28T15:17:07.363 に答える
0

できるよ

Obj j = session.get(Object.class(), id);
if (j != null)
   session.merge(myObj);
else
   session.saveOrUpdate(myObj);
于 2008-11-28T16:41:38.003 に答える
-1

hibernate.saveOrUpdate() を呼び出して、オブジェクトがデータベースにあるかどうかを確認し、存在する場合は更新し、存在しない場合は保存 (挿入) します。

于 2008-11-28T15:15:48.537 に答える