6

NHibernateを使用してクラスPersonをデータベースにマップしています。DBからオブジェクトをロードし、それを別のクライアントに送信します。最初のクライアントは、NameプロパティとCountryプロパティを変更します。2番目のクライアントはNameプロパティのみを変更します。次に、両方が変更されたオブジェクトをサーバーに返します。最初のクライアントからデータを保存すると(次に正しく保存され、両方)、名前と国が更新されました。2番目のクライアントからデータを保存するとき-問題があります。最初のクライアントからのデータを上書きし、国の新しい名前と初期値を保存しました。

名前の値のみを保存し、国の値を上書きしないようにNHibernateに指示するにはどうすればよいですか?

public class Person
{
    public string Name { get; set; }
    public string Country { get; set; }
}

public static List<Person> GetEntities()
{
    var factory = CreateSessionFactory();
    using (ISession session = factory.OpenSession())
    {
        return session.CreateCriteria<Person>().List<Person>();                
    }
}

public static void SaveEntities(List<Person> entities)
{
    var factory = CreateSessionFactory();
    using (ISession session = factory.OpenSession())
    {
         using (var t = session.BeginTransaction())
         {
             foreach (var person in entities)
             {
                 session.Merge(person);
             }

             t.Commit();
        }
    }
}

PS:私の悪い英語でごめんなさい

4

4 に答える 4

15

実際には、を使用して「ダーティ」フィールドを具体的に更新するようにNHibernateに指示できますDynamic Update

詳細:http ://ayende.com/blog/3946/nhibernate-mapping-concurrency

于 2011-06-07T20:26:32.603 に答える
3

これは並行性の問題です。2番目のクライアントは、データを読み取ってからデータが変更されたことを認識しないため、その変更によって最初のクライアントの変更が上書きされます。これは、NHibernateでいくつかの方法の1つによって処理できます。最も一般的な方法は、バージョン列を使用することです。

この問題は簡単に防ぐことができます。より大きな問題は、発生したときにユーザーに適切なフィードバックを提供することです。

于 2011-06-07T16:16:22.273 に答える
1

答えは:できません。NHは名前だけが変わったことを知りません。

同時編集を許可しないことで、これを回避できます。たとえば、NHの楽観的ロックメカニズムによるものです。2番目のクライアントはを取得しStaleObjectStateExceptionます。

2つのクライアントの編集が実際には同時に行われていない場合(ただし、両方が同じオブジェクト状態に基づいている場合)、編集する前に、2番目のクライアントが最初のクライアントの変更を取得することを確認する必要があります。たとえば、エディタを開く前に実際の状態を取得したり、サーバーから変更された通知を送信したりします。

同時編集を続けたい場合は、かなりの作業が必要です。クライアントは、実際に何が変更されたかについての情報を提供する必要があります。次に、これらの値のみをコピーする必要があります。これは大変な作業です。その場合でも、そのようにマージされた値が適合しないという問題が発生する可能性があります。

于 2011-06-07T17:47:18.647 に答える
0

Jamie Ideが正しく指摘しているように、発生しているのは同時実行の問題であり、マッピングの問題ではありません。

オブジェクトのnhibernateマッピングを作成すると、セッションがフラッシュされると、それらのオブジェクトに存在するすべてのデータがデータベースに保存(または更新)されます。更新する個々のフィールドを指定することはできません。すべてまたはまったくありません。

もう1つの(無関係な)ポイントとして、サンプルコードは、エンティティの各操作で新しいセッションファクトリをインスタンス化しています。セッションファクトリは作成に費用がかかるため、これは一般的に悪い考えです。グローバルコンテキスト(シングルトン)を介してセッションファクトリを管理し、一度作成して、必要に応じてセッション(軽量オブジェクト)を生成することをお勧めします。

于 2011-06-07T17:00:38.460 に答える