Выбирает ли NHibernate версию обновления?

У меня есть очень простое отображение, как:

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 */

2 ответа

Решение

Хорошо, я нашел, что было не так. В классе, который я тестировал, я отобразил коллекцию и использовал "ленивый экземпляр" этой коллекции, например:

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

Оказывается, это не пойдет с NH. Эта вещь, когда NH заменил экземпляр вашей коллекции собственной реализацией, вызвала у меня много головной боли, будучи новичком NH. Надеюсь, что другие "новички" могут извлечь уроки из этого. Если вы хотите знать все, что вы можете сделать неправильно по этому вопросу, прочитайте мои сообщения.

Я нашел также один... Проблема была там:

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" />
Другие вопросы по тегам