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

我还发现了一个......问题就在那里:

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 回答