1

ユーザーが注文を開いて変更を加え、データベースに保存できるシンプルなアプリケーションがあります。注文が開かれると、このようにデータベースから注文を取得します

ISession session = SessionFactory.OpenSession();

...

Order order = session.Query<Order>()
                     .Where(o => o.Id == id)
                     .FirstOrDefault();

order.Commentsの遅延読み込みを有効にするために、注文が閉じられるまでセッションを開いたままにします。マッピングは次のとおりです。

<class name="Order">
    <id name="Id">
        <generator class="identity" />
    </id>    

...

    <set name="Comments" access="field.camelcase-underscore" cascade="all-delete-orphan"    lazy="true" order-by="Created">
      <key column="OrderId" />
      <one-to-many class="Comment" />
    </set>     
</class>

<class name="Comment" table="OrderComment" lazy="false">
    <id name="Id">
      <generator class="identity" />
    </id>
    <many-to-one name="Author" />
    <property name="Created" />
    <property name="Text" length="1000" />
</class>

このアプリは、注文が開いている間、閉じる前に数回保存できるように設計されています。私はこのように保存します:

using (ITransaction trans = session.BeginTransaction())
{
    session.SaveOrUpdate(order)
    trans.Commit();
}

最後に、ユーザーが注文を閉じると、セッションを破棄します。

ここに問題があります。ユーザーがコメントを追加して保存し、注文を閉じる前に別のコメントを追加して再度保存すると、2回目の保存中に最初のコメントが削除されます。2番目の保存から出力されるSQLは次のとおりです。

NHibernate: INSERT INTO OrderComment (Id, Author, Created, Text) VALUES (hibernate_sequence.nextval, :p0, :p1, :p2) returning Id into :nhIdOutParam;:p0 = 1 [Type: Int32 (0)], :p1 = 14.01.2013 12:53:20 [Type: DateTime (0)], :p2 = '2' [Type: String (0)], :nhIdOutParam = NULL [Type: Int32 (0)]

**NHibernate: UPDATE OrderComment SET OrderId = null WHERE OrderId = :p0 AND Id = :p1;:p0 = 465 [Type: Int32 (0)], :p1 = 591 [Type: Int32 (0)]**

NHibernate: UPDATE OrderComment SET OrderId = :p0 WHERE Id = :p1;:p0 = 465 [Type: Int32 (0)], :p1 = 592 [Type: Int32 (0)]

したがって、問題は太字の行です。最初のコメントのOrderIdがnullに設定されています。誰かが私の理由を教えてもらえますか?

ここでnHibernateを使用する方法に何か問題がありますか?私がしていることを繰り返すには:

  1. セッションを開く
  2. オブジェクトを取得する
  3. ユーザーがオブジェクトを更新します
  4. トランザクションを開始し、session.SaveOrUpdate(object)を呼び出してから、トランザクションをコミットして、オブジェクトを保存します。
  5. 手順3と4を何度でも繰り返します。
  6. セッションを破棄します。

これは許容できる使用方法nHibernateですか?

編集

Orderクラスのcommentsプロパティは次のとおりです。

ICollection<Comment> _comments = new List<Comment>();
public virtual ReadOnlyCollection<Comment> Comments
{
    get 
    {
        return _comments.ToList().AsReadOnly(); 
    }
}

次に、次のメソッドを呼び出してコメントを追加します。

public virtual void AddComment(Comment comment)
{
    _comments.Add(comment);    
}

 ...

Comment comment = new Comment()
{
    Author = User.Current,
    Created = DateTime.Now,
    Text = text
};

order.AddComment(comment);

これがCommentクラスです。Idは基本クラスに実装されていますPersistentObject<T>

public class Comment : PersistentObject<int>
{        
    public User Author { get; private set; }
    public DateTime Created { get; private set; }
    public string Text { get; private set; }                                             
}

public abstract class PersistentObject<T>
{        
    public virtual T Id { get; protected internal set; }       

    public override bool Equals(object obj)
    {
        // If both objects have not been saved to database, then can't compare Id because this
        // will be 0 for both.  In this case use reference equality.

        PersistentObject<T> other = obj as PersistentObject<T>;
        if (other == null)
            return false;

        bool thisIsDefault = object.Equals(Id, default(T));
        bool otherIsDefault = object.Equals(other.Id, default(T));

        if (thisIsDefault && otherIsDefault)
            return object.ReferenceEquals(this, other);
        else if (thisIsDefault || otherIsDefault)
            return false;
        else
            return object.Equals(this.Id, other.Id);
    }

    public override int GetHashCode()
    {
        return Id.GetHashCode();
    }        
}
4

2 に答える 2

1

コメントのコレクションにアイテムを追加するために使用されるコードを表示できますか?

NHibernateにコメントのコレクションを管理させる必要があるため、Commentsプロパティをまたはnew List<OrderComment>同様のものに再設定しないようにし、同じNHibernateインスタンス化プロキシを維持し、必要に応じてその値を追加/削除/クリアするようにします。

于 2013-01-14T15:05:47.553 に答える
1

HashCode私はから取られるべきではないと思いますIdOrder.Commentsは、ハッシュに基づくセットです。コメントはすべて0最初にIDがあります。HashCodeコレクションに追加するとき、それがであるときに取られます0

于 2013-01-14T16:14:00.740 に答える