2

次のような非常に単純なマッピングがあります。

public abstract class EntityMap<TEnt, TId, TDto> : ClassMap<TEnt>
    where TEnt: Entity<TId, TDto> 
    where TDto : DataTransferObject<TDto, TId>
{
    protected EntityMap()
    {
        Id(x => x.Id).GeneratedBy.GuidComb();
        Map(x => x.Name).Not.Nullable().Unique().Length(255);
        Version(x => x.Version);
        SelectBeforeUpdate();
    } 

このマッピングを使用して、次のようなテストを実行します。

    [TestMethod]
    public void ThatVersionDoesNotChangedAfterOnlyAReadAction()
    {
        var services = BrandServices.WithDto(BrandTestFixtures.GetDto()).Get();
        Assert.AreEqual(1, services.Version);
        Context.CurrentSession().Transaction.Commit();
        Context.CurrentSession().Transaction.Begin();
        var brand = BrandServices.Brands.Single(x => x.Name == BrandTestFixtures.GetDto().Name);
        Assert.AreEqual(1, brand.Version);
    }

したがって、このテストでは、エンティティ マップにマップされたオブジェクトを作成し、このオブジェクトをデータベースに挿入します。意味的には、オブジェクトのバージョンは 1 つだけにする必要があります。ただし、コミットすると、挿入されたオブジェクトが新しいバージョンですぐに更新されます。また、バージョンを確認するために再度オブジェクトを取得すると、バージョンが再びインクリメントされます。予想されるバージョンは 1 である必要があります。テスト ブランドのバージョンは 3 ですが、データベースではバージョンが 4 です!?!?!

さまざまな種類のマッピング オプションを試しました。私にとって最も不可解な部分は、オブジェクトがデータベースから取得された瞬間にバージョンがインクリメントされることです。複数の双方向関係を持つ私の完全なアプリケーションでは、これは深刻な問題につながります。この動作を変更する方法はありますか、それとも自家製のバージョン管理メカニズムに頼る必要がありますか?

-- statement #1
select brand0_.Id      as Id0_,
       brand0_.Version as Version0_,
       brand0_.Name    as Name0_
from   [Brand] brand0_

-- statement #2
select brand0_.Id      as Id0_,
       brand0_.Version as Version0_,
       brand0_.Name    as Name0_
from   [Brand] brand0_

-- statement #3
INSERT INTO [Brand]
           (Version,
            Name,
            Id)
VALUES     (1 /* @p0_0 */,
            'Dynatra' /* @p1_0 */,
            '8ca15020-2e23-4ace-adff-9f4800b706d5' /* @p2_0 */)

-- statement #4
UPDATE [Brand]
SET    Version = 2 /* @p0 */,
       Name = 'Dynatra' /* @p1 */
WHERE  Id = '8ca15020-2e23-4ace-adff-9f4800b706d5' /* @p2 */
       AND Version = 1 /* @p3 */

-- statement #5
commit transaction

-- statement #6
begin transaction with isolation level: Unspecified

-- statement #7
UPDATE [Brand]
SET    Version = 3 /* @p0 */,
       Name = 'Dynatra' /* @p1 */
WHERE  Id = '8ca15020-2e23-4ace-adff-9f4800b706d5' /* @p2 */
       AND Version = 2 /* @p3 */

-- statement #8
select brand0_.Id      as Id0_,
       brand0_.Version as Version0_,
       brand0_.Name    as Name0_
from   [Brand] brand0_

-- statement #9
UPDATE [Brand]
SET    Version = 4 /* @p0 */,
       Name = 'Dynatra' /* @p1 */
WHERE  Id = '8ca15020-2e23-4ace-adff-9f4800b706d5' /* @p2 */
       AND Version = 3 /* @p3 */
4

2 に答える 2

1

わかりました、私は何が悪いのかを見つけました。私がテストしていたクラスでは、コレクションをマッピングし、そのコレクションの「レイジーインスタンス化」を次のように使用していました。

    public virtual ISet<Product> Products
    {
        get  { return _products ?? (_products = new HashedSet<Product>(); }
        protected set { _products = value;}
    }

これはNHではダメであることが判明しました。NHがコレクションインスタンスを独自の実装に置き換えるというこのことは、NHの初心者であるため、私に多くの頭痛の種を引き起こしました。他の「初心者」がこれから学ぶことができることを願っています。このテーマで間違ってできることをすべて知りたい場合は、私の投稿を読んでください。

于 2011-08-26T09:24:24.637 に答える
-1

私も1つ見つけました...問題はそこにありました:

public enum ContractValidationImportance
{
    Low,
    Neutral,
    Intermediate,
    High
}

...entity.cs
.....

    private ContractValidationImportance _validationImportance;
    public ContractValidationImportance ValidationImportance
    {
        get { return _validationImportance; }
        set { _validationImportance = value; }
    }

... entity.hbm.xml

<property name="ValidationImportance" column="ValidationImportance" type="Int32" />
于 2011-10-22T20:44:16.737 に答える