NHibernate:独家锁定

Fre*_*els 14 nhibernate locking

在NHibernate中,我想检索一个实例,并在表示数据库中检索到的实体的记录上放置一个独占锁.

现在,我有这个代码:

With.Transaction (session, IsolationLevel.Serializable, delegate
{
    ICriteria crit = session.CreateCriteria (typeof (TarificationProfile));

    crit.SetLockMode (LockMode.Upgrade);

    crit.Add (Expression.Eq ("Id", tarificationProfileId));

    TarificationProfile profile = crit.UniqueResult<TarificationProfile> ();

    nextNumber = profile.AttestCounter;

    profile.AttestCounter++;

    session.SaveOrUpdate (profile);
});
Run Code Online (Sandbox Code Playgroud)

如您所见,我将此Criteria的LockMode设置为"Upgrade".这会为SQL Server发出一个SQL语句,它使用updlockrowlock锁定提示:

SELECT ... FROM MyTable with (updlock, rowlock)
Run Code Online (Sandbox Code Playgroud)

但是,我希望能够使用真正的独占锁.也就是说,防止其他人可以读取这个相同的记录,直到我释放锁定.换句话说,我希望能够使用xlock锁定提示,而不是updlock.

我不知道(甚至是否)我能做到这一点......也许有人可以给我一些关于这个的提示:)

如果确实有必要,我可以使用NHibernate的SQLQuery功能,并编写自己的SQL查询,但是,我想尽可能避免这种情况.

Lac*_*che 7

HQL DML查询将完成您的更新,而无需锁定.

这在NHibernate 2.1中可用,但尚未在参考文档中.Java hibernate文档非常接近NHibernate实现.

假设您正在使用ReadCommitted Isolation,那么您可以安全地在事务中读取您的值.

With.Transaction (session, IsolationLevel.Serializable, delegate
{
    session.CreateQuery( "update TarificationProfile t set t.AttestCounter = 1 + t.AttestCounter where t.id=:id" )
        .SetInt32("id", tarificationProfileId)
        .ExecuteUpdate();

    nextNumber = session.CreateQuery( "select AttestCounter from TarificationProfile where Id=:id" )
        .SetInt32("id", id )
        .UniqueResult<int>();
}
Run Code Online (Sandbox Code Playgroud)

根据您的表名和列名,生成的SQL将是:

update TarificationProfile
set    AttestCounter = 1 + AttestCounter
where  Id = 1 /* @p0 */

select tarificati0_.AttestCounter as col_0_0_
from   TarificationProfile tarificati0_
where  tarificati0_.Id = 1 /* @p0 */
Run Code Online (Sandbox Code Playgroud)