首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >正确处理StaleObjectStateException

正确处理StaleObjectStateException
EN

Stack Overflow用户
提问于 2015-04-17 19:54:46
回答 1查看 970关注 0票数 1

我有一个可由多个程序访问的SQL Server数据库。程序使用Fluent NHibernate作为对象关系映射,用C#编写。但是,根据域逻辑,数据库中有一些对象(称为令牌)不应该允许由多个进程/线程等并发处理它们。

我试图通过NHIbernate版本锁定来实现这一点。我有以下映射

代码语言:javascript
复制
mapping.OptimisticLock.Version();
mapping.Version(token => token.VersionTimestamp).Generated.Always().UnsavedValue(null).Access.Property().CustomSqlType("timestamp").Nullable();

和以下代码:

代码语言:javascript
复制
var token = Session.Get<Token>(tokenId);

if (token.Status != TokenStatus.Available)
    return new FailedResult("Token not available");

try
{
    token.Status = TokenStatus.Locked;
    Session.SaveOrUpdate(token);
}
catch (StaleObjectStateException)
{
    WriteLogsToDb(); // <- another StaleObjectStateException thrown here
    return new FailedResult("Could not acquire token");
}

ProcessToken(token); // do stuff that isn't allowed to be done concurrently by multiple threads/processes

token.Status = TokenStatus.Available;
Session.SaveOrUpdate(token);

return new SuccessResult();

问题是,在获得StaleObjectStateException之后,我无法将任何其他内容保存到数据库中(即使是没有版本映射的实体)。我得到了另一个StaleObjectStateException。但在我无法锁定令牌后,我真的需要将日志和其他一些东西写入数据库中。

正确的做法是什么?NHibernate这种行为的原因是什么?

EN

回答 1

Stack Overflow用户

发布于 2015-04-19 21:49:38

会话是UoW,它在刷新操作期间合并您所做的所有更改并接受它。因为你在刷新过程中得到了一个异常(不带事务的SaveOrUpdate执行刷新),你的对象(令牌)仍然被标记为脏的,并且在下一次刷新时尝试保存它,如果它仍然被锁定,你会再次得到一个异常。

要避免这种情况,您必须在保存任何其他内容之前从会话中删除对象:

代码语言:javascript
复制
try
{
    token.Status = TokenStatus.Locked;
    Session.SaveOrUpdate(token);
}
catch (StaleObjectStateException)
{
    Session.Evict(token); // <- remove token from session

    WriteLogsToDb(); // <- another StaleObjectStateException thrown here
    return new FailedResult("Could not acquire token");
}  
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/29698473

复制
相关文章

相似问题

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