首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Fluent NHibernate乐观锁

Fluent NHibernate乐观锁
EN

Stack Overflow用户
提问于 2013-07-03 00:57:23
回答 2查看 4.9K关注 0票数 3

我正在尝试使用fluent nhibernate配置操作锁定。

有很多信息,但似乎没有一个符合我所处的情况。我的class和map如下(为简洁起见进行了编辑):

实体:

代码语言:javascript
复制
public class EmailGroup : CRUDDomainObject<EmailGroup>
{        
    public virtual string Id { get; set; }
    public virtual MailServer Server { get; set;}
    public virtual string FromAddress { get; set;}
    public virtual string ToAddress { get; set;}
    public virtual long Version { get; set; }    
}

映射:

代码语言:javascript
复制
public class EmailGroupMap : ClassMap<EmailGroup>
{
    public const string TABLE_ID = "EMAILGROUP";

    public const string FIELD_ID = "EMAILID";
    public const string FIELD_MAIL_SERVER = "MAILSERVID";
    public const string FIELD_FROM_ADDRESS = "EMLFROM";
    public const string FIELD_TO_ADDRESS = "EMLTO";
    public const string FIELD_VERSION = "VERSION";

    public EmailGroupMap()
    {
        Table(TABLE_ID);

        Id(x => x.Id)
            .Column(FIELD_ID)
            .Not.Nullable()
            .GeneratedBy.Assigned()
            .Length(12);

        References(x => x.Server)
            .Column(FIELD_MAIL_SERVER)
            .NotFound.Ignore();

        Map(x => x.FromAddress)
            .Column(FIELD_FROM_ADDRESS)
            .Not.Nullable()
            .Length(120);

        Map(x => x.ToAddress)
            .Column(FIELD_TO_ADDRESS)
            .Not.Nullable()
            .Length(1000);

        Version(X => X.Version)
            .Column(FIELD_VERSION)
            .Generated.Always()
            .UnsavedValue("0")
            .Access.Property();

        DynamicUpdate();

        OptimisticLock.Version();
    }
}

在我看来一切都很好,但是当我加载实体并修改它时,版本号并没有递增。同样,如果我手动增加版本,当会话打开时,我得不到StaleObjectException。

对于更有经验的人来说,这个配置是否有效?如果是这样,我还会遗漏什么呢?

更新:

在实现数据库管理的时间戳之后,version列(当然)是递增的。然而,NHibernate并不乐观地将该行视为锁定的。我从SQL服务器捕获了update查询,以检查where子句(为简洁起见被截断):

代码语言:javascript
复制
exec sp_executesql N'UPDATE [EMAILGROUP] 
SET [EMLDESC] = @EMLDESC, [MAILSERVID] = @MAILSERVID, [EMLFROM] = @EMLFROM, [EMLTO] = @EMLTO, [EMLCC] = @EMLCC, [EMLBCC] = @EMLBCC 
WHERE [EMAILID] = @EMAILID'
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2013-07-03 15:29:21

为什么要指定Generated.Always()?这告诉NHibernate这不是一个真正的列,而是由数据库计算的。文档:http://nhibernate.info/doc/nh/en/index.html#mapping-generated

去掉它,它就可以工作了。

票数 2
EN

Stack Overflow用户

发布于 2013-07-03 12:12:00

对于Version和SQL Server (不确定是否属于您的情况),最典型的配置是SQL型timestamp (过时)或更好的rowversion。这应该映射到C# byte[]。所以这些改变应该能解决这个问题:

1)服务器上的版本列必须是rowversion (或timestamp)类型。这样的列会在与当前行相关的任何更改时自动更新。每个表只能存在一个这样的列

2)实体应如下所示

代码语言:javascript
复制
public class EmailGroup : CRUDDomainObject<EmailGroup>
{        
   ...
   public virtual byte[] Version { get; set; }  

3)流畅的映射代码应该保持原样。这应该是一个流利的映射者的工作来做后面的技巧。我们需要实现的是这样的:

代码语言:javascript
复制
<version name="Version" generated="always" unsaved-value="null"  type="BinaryBlob">
    <column name="Version" not-null="false" sql-type="timestamp"/>
</version>

请在此处查看更多信息:http://ayende.com/blog/3946/nhibernate-mapping-concurrency

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/17431459

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档