nhibernate 3.0 оптимистическая блокировка и связанные объекты - PullRequest
1 голос
/ 04 июня 2011

Я заметил в своей базе данных (SQL Server), что столбец, который я использую для управления версиями, обновляется для сущности всякий раз, когда эта сущность добавляется в связанную таблицу.

Так, например, если у меня есть сущность Person и я добавляю Person к Club, запись Person в базе данных будет иметь новую версию.Конечно, в базе данных это запись Club, которая добавляется / обновляется с помощью первичного ключа Person.

Я немного удивлен таким поведением, потому что других данных дляPerson сущность меняется.

Мой вопрос, есть ли способ отключить это;то есть, чтобы столбец версии обновлялся только при изменении данных в этой строке.Какими могут быть последствия такой конфигурации?

РЕДАКТИРОВАТЬ Вот реальный код

Модель

public partial class ObligationProgramFund : IMyObject
{
    private System.Int32 _id;
    // ... many other properties
    private IList<ObligationProgramFundOrganization> _obligationPFOrganizations;
    private System.Byte[] _recordVersion;

    public ObligationProgramFund() : base()
    {
        _obligationPFOrganizations = new List<ObligationProgramFundOrganization>();
    }

    public virtual System.Int32 Id
    { 
        get { return _id; }
        set { _id = value; }
    }

    public virtual IList<ObligationProgramFundOrganization> ObligationPFOrganizations
    {
        get { return _obligationPFOrganizations; }
        set { _obligationPFOrganizations = value; }
    }

    public virtual System.Byte[] RecordVersion
    { 
        get { return _recordVersion; }
        set { _recordVersion = value; }
    }
}

public partial class ObligationProgramFundOrganization : IMyObject
{
    private ObligationProgramFund _obligationProgramFund;
    private System.Int32 _id;
    private Organization _organization;
    private System.Byte[] _recordVersion;
    // .. other properties

    public ObligationProgramFundOrganization() : base()
    {
    }

    public virtual System.Int32 Id
    { 
        get { return _id; }
        set { _id = value; }
    }

    public virtual System.Byte[] RecordVersion
    { 
        get { return _recordVersion; }
        set { _recordVersion = value; }
    }

    public virtual ObligationProgramFund ObligationProgramFund
    {
        get { return _obligationProgramFund; }
        set { _obligationProgramFund = value; }
    }

    public virtual Organization Organization
    {
        get { return _organization; }
        set { _organization = value; }
    }
}

public partial class Organization : IMyObject
{
    private IList<ObligationProgramFundOrganization> _obligationPFOrganizations;
    private System.Int32 _id;
    private System.Byte[] _recordVersion;
    // other properties

    public Organization() : base()
    {
        _obligationPFOrganizations = new List<ObligationProgramFundOrganization>();
    }

    public virtual System.Int32 Id
    { 
        get { return _id; }
        set { _id = value; }
    }

    public virtual System.Byte[] RecordVersion
    { 
        get { return _recordVersion; }
        set { _recordVersion = value; }
    }

    public virtual IList<ObligationProgramFundOrganization> ObligationPFOrganizations
    {
        get { return _obligationPFOrganizations; }
        set { _obligationPFOrganizations = value; }
    }
}

Отображение

public partial class ObligationProgramFundMap : ClassMap<ObligationProgramFund>
{
    public ObligationProgramFundMap()
    {
        Table("[MySchema2].[dbo].[ObligationProgramFund]");
        OptimisticLock.Version();
        DynamicUpdate();
        LazyLoad();

        Id(x=>x.Id)
            .Access.CamelCaseField(Prefix.Underscore)
            .Column("[Id]")
            .GeneratedBy.Identity();
        Version(x=>x.RecordVersion)
            .Access.CamelCaseField(Prefix.Underscore)
            .Column("[RecordVersion]")
                .CustomSqlType("timestamp")
                .Not.Nullable()
            .UnsavedValue("null")
            .CustomType("BinaryBlob")
            .Generated.Always();
            // other properties/components

        HasMany(x=>x.ObligationPFOrganizations)
            .Access.CamelCaseField(Prefix.Underscore)
            .Cascade.AllDeleteOrphan()
            .Fetch.Select()
            .Inverse()
            .LazyLoad()
            .KeyColumns.Add("ObligationProgramFundId"); 
        } 
    } 

public partial class ObligationProgramFundOrganizationMap : ClassMap<ObligationProgramFundOrganization>
{
    public ObligationProgramFundOrganizationMap()
    {
        Table("[MySchema2].[dbo].[ObligationProgramFundOrganization]");
        OptimisticLock.Version();
        DynamicUpdate();
        LazyLoad();

    Id(x=>x.Id)
        .Access.CamelCaseField(Prefix.Underscore)
        .Column("[Id]")
        .GeneratedBy.Identity();
    Version(x=>x.RecordVersion)
        .Access.CamelCaseField(Prefix.Underscore)
        .Column("[RecordVersion]")
            .CustomSqlType("timestamp")
            .Not.Nullable()
        .UnsavedValue("null")
        .CustomType("BinaryBlob")
        .Generated.Always();

    // other properties      

    References(x=>x.ObligationProgramFund)
        .Access.CamelCaseField(Prefix.Underscore)
        .Cascade.SaveUpdate()
        .Fetch.Select()
        .Columns("ObligationProgramFundId");
    References(x=>x.Organization)
        .Access.CamelCaseField(Prefix.Underscore)
        .Cascade.SaveUpdate()
        .Fetch.Select()
        .Columns("OrganizationId");
    } 
}

public partial class OrganizationMap : ClassMap<Organization>
{
    public OrganizationMap()
    {
        Table("[MySchema2].[dbo].[Organization]");
        OptimisticLock.Version();
        DynamicUpdate();
        LazyLoad();

        Id(x=>x.Id)
            .Access.CamelCaseField(Prefix.Underscore)
            .Column("[Id]")
            .GeneratedBy.Identity();
        Version(x=>x.RecordVersion)
            .Access.CamelCaseField(Prefix.Underscore)
            .Column("[RecordVersion]")
            .CustomSqlType("timestamp")
            .Not.Nullable()
            .UnsavedValue("null")
            .CustomType("BinaryBlob")
            .Generated.Always();

        // other properties

        HasMany(x=>x.ObligationPFOrganizations)
            .Access.CamelCaseField(Prefix.Underscore)
            .Cascade.AllDeleteOrphan()
            .Fetch.Select()
            .Inverse()
            .LazyLoad()
            .KeyColumns.Add("OrganizationId");
    } 
}

Таким образом, мои сущности

Organization 1 - ∞ ObligationProgramFundOrganization ∞ - 1 ObligationProgramFund

Проблема, с которой я столкнулся при создании новой ObligationProgramFundOrganization (ассоциативная таблица), обновляется версия записи для ObligationProgramFund.Фактический senario - это то, что у меня есть таблица ObligationProgramFundOrganizations в форме редактирования ObligationProgramFund.ObligationProgramFundOrganization добавляется через вызовы AJAX.Когда я иду, чтобы затем сохранить ObligationProgramFund, я получаю исключение параллелизма.Я уверен, что никакой другой пользователь на самом деле не редактировал ObligationProgramFund, поскольку он все работает локально.

1 Ответ

0 голосов
/ 21 марта 2013

(я отправил ответ на похожий вопрос: Почему ссылка на NHibernate UPDATE? )

Вы указали столбец версии.Это означает, что любое изменение свойства (даже коллекции) инициирует обновление версии.

Чтобы предотвратить изменение версии определенным свойством / коллекцией, в сопоставлении xml должно быть установлено свойство optimistic-lock = "false".

...