nhibernate 3.0乐观锁和相关实体

时间:2011-06-03 21:18:15

标签: nhibernate versioning

我在我的数据库(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的记录版本会更新。

实际的情况是我在ObligationProgramFund编辑表格上有一个ObligationProgramFundOrganizations表。通过AJAX调用添加ObligationProgramFundOrganization。当我去保存ObligationProgramFund时,我得到一个并发异常。我确信没有其他用户实际编辑过ObligationProgramFund,因为它全部在本地运行。

1 个答案:

答案 0 :(得分:0)

(我已经发布了一个类似问题的答案:Why NHibernate UPDATE reference entity?

您指定了版本列。这意味着任何属性更改(甚至集合)都会触发版本更新。

为了防止某个属性/集合更改版本,应在xml映射中设置optimistic-lock =“false”属性。