1

今日、私は自分のドメインモデルでいくつかのことをテストしていましたが、その動作が期待したものではないことに気づきました。

Customers-Orders単純なモデルを作成する際に問題を切り分けようとしました。

これが私のマッピングです。

お客様:

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">
  <class xmlns="urn:nhibernate-mapping-2.2" name="NHVariousTests.Domain.Customer, NHVariousTests" table="Customers">
    <id name="Code" type="System.Guid">
        <column name="CustomerCode" />
        <generator class="guid.comb" />
    </id>
    <version name="Version" type="System.Int32" unsaved-value="0" access="backfield"">
        <column name="Version" not-null="true" />
    </version>
    <property name="Description" type="AnsiString">
          <column name="Description" not-null="false" />
    </property>   
    <set name="Orders" access="field.pascalcase-underscore" cascade="all-delete-orphan" inverse="true" lazy="true">
        <key column="CustomerCode" />
        <one-to-many class="NHVariousTests.Domain.Order, NHVariousTests" />
    </set>
  </class>
</hibernate-mapping>

注文:

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2">
  <class xmlns="urn:nhibernate-mapping-2.2" name="NHVariousTests.Domain.Order, NHVariousTests" table="Orders">
    <id name="Code" type="System.Guid">
        <column name="OrderCode" />
        <generator class="guid.comb" />
    </id>
    <version name="Version" type="System.Int32" unsaved-value="0" access="backfield">
        <column name="Version" not-null="true" />
    </version>
    <property name="Description" type="AnsiString">
        <column name="Description" not-null="false" />
    </property>   
    <many-to-one class="NHVariousTests.Domain.Customer, NHVariousTests" name="Customer">
        <column name="CustomerCode" not-null="true" />
    </many-to-one>
  </class>
</hibernate-mapping>

Orderのクラスはとてもシンプルです:

public class Order : EntityGuid
{
    public Order()
    {
    }

    public virtual string Description { get; set; }

    public virtual Customer Customer { get; set; }
}

これが私のCustomerクラスです:

public class Customer : EntityGuid
{
    public Customer()
    {
        this._Orders = new HashSet<Order>();
    }

    public virtual string Description { get; set; }

    #region Orders

    private readonly ICollection<Order> _Orders = null;

    public virtual ReadOnlyCollection<Order> Orders
    {
        get { return (new List<Order>(_Orders).AsReadOnly()); }
    }

    public virtual bool AddOrder(Order order)
    {
        if ((order != null) && (!this._Orders.Contains(order)))
        {
            order.Customer = this;
            this._Orders.Add(order);
            return (true);
        }
        return (false);
    }

    public virtual bool RemoveOrder(Order order)
    {
        if ((order != null) && (this._Orders.Contains(order)))
        {
            this._Orders.Remove(order);
            order.Customer = null;
            return (true);
        }
        return (false);
    }

    #endregion
}

ICollection<Order>この最初の例では、として作成されたプライベートを使用していHashSet<Order>ます。

このコードを実行すると:

using (var session = sessionFactory.OpenSession())
{
    using (var tx = session.BeginTransaction())
    {
        var customer = new Domain.Customer() { Description = "ACME Ltd" };

        var order = new Domain.Order() { Description = "Coffee" };
        customer.AddOrder(order);

        order = new Domain.Order() { Description = "Milk" };
        customer.AddOrder(order);

        session.Save(customer);

        tx.Commit();
    }
}

INSERT顧客のとINSERT注文の2つを見ることができますが、顧客のも持っUPDATEています。

ここに画像の説明を入力してください

CustomerクラススイッチをIesiコレクションに変更した場合:

public class Customer : EntityGuid
{
    public Customer()
    {
        this._Orders = new Iesi.Collections.Generic.HashedSet<Order>();
    }

    public virtual string Description { get; set; }

    #region Orders

    private readonly ICollection<Order> _Orders = null;

    public virtual ReadOnlyCollection<Order> Orders
    {
        get { return (new List<Order>(_Orders).AsReadOnly()); }
    }

    public virtual bool AddOrder(Order order)
    {
        if ((order != null) && (!this._Orders.Contains(order)))
        {
            order.Customer = this;
            this._Orders.Add(order);
            return (true);
        }
        return (false);
    }

    public virtual bool RemoveOrder(Order order)
    {
        if ((order != null) && (this._Orders.Contains(order)))
        {
            this._Orders.Remove(order);
            order.Customer = null;
            return (true);
        }
        return (false);
    }

    #endregion
}

私は期待される振る舞いをしました:

ここに画像の説明を入力してください

これは私のEntityGuidクラスです:

public abstract class EntityGuid : EntityWithTypedId<Guid>, IAuditedEntity
{
    public EntityGuid()
    {
        this.CreatedDate = DateTime.Now;
        this.UpdatedDate = DateTime.Now;
        this.CreatedBy = "";
        this.UpdatedBy = "";
    }

    public virtual DateTime CreatedDate { get; set; }
    public virtual string CreatedBy { get; set; }

    public virtual DateTime UpdatedDate { get; set; }
    public virtual string UpdatedBy { get; set; }

    public virtual int Version { get; private set; }

    public virtual bool IsTransient()
    {
        return (EntityWithTypedId<Guid>.Equals(this.Code, default(Guid)));
    }

    public virtual bool IsTransient(EntityWithTypedId<Guid> obj)
    {
        return obj != null && Equals(obj.Code, default(Guid));
    }

}

何が起こっているのかを理解するのを手伝ってくれる人はいますか?

よろしく。

誰かが本当にコードを見てみたいと思っているなら。私はすべてをきれいにし、それを可能な限り単純にしました。ここからダウンロードできます(NH_CollectionProblems)。

NHibernate3.3.2.4000を使用しています

4

2 に答える 2

1

期待する動作は間違っています。バージョン管理されたエンティティのコレクションを変更すると、バージョンが更新されることを期待する必要があります。この動作は、コレクションをマッピングするためのドキュメントで説明されており、コレクションを無効にする方法も説明されています。

optimistic-lock(オプション-デフォルトはtrue):コレクションの状態に変化する種は、所有するエンティティのバージョンの増分になります。(1対多の関連付けの場合、この設定を無効にするのが妥当な場合がよくあります。)

プロジェクトをプルダウンし、この設定を変更すると、発行される更新が切り替わることを確認しました:false =更新なし、true(デフォルト)=更新。ただし、IesiHashedSetを使用して期待される動作を取得できませんでした。バグだと思いますが、今はもう時間がありません。

于 2013-01-11T13:45:51.433 に答える
1

また...

  • NH 4.0(BCLのISetが利用可能な.net 4.0を対象とする)を待ちます。アルファリリースはまもなく利用可能になります。
  • https://bitbucket.org/jfromaniello/nhibernate.setfornet4を使用します。nuget、http: //nuget.org/packages/NHibernate.SetForNet4で入手できます。
于 2013-01-08T12:12:37.447 に答える