如何在实体框架5中增加/减少多用户安全 [英] how to inc/dec multi user safe in entity framework 5
问题描述
什么是一种干净,安全的递增或递减整数字段的方法。
What is a clean, safe way to increment or decrement an integer field.
我将sql server 2012与EntityFramework 5.x结合使用
i use sql server 2012 in combination with entityframework 5.x
我正在寻找与互锁的增量/减量等效的方法。
I look for an equivalent to interlocked increment / decrement.
推荐答案
是使用乐观并发。
说,您有一个简单的实体,其整数字段 Counter
递增或递减:
Say, you have a simple entity with an integer field Counter
that you want to increment or decrement:
public class SomeEntity
{
public int SomeEntityId { get; set; }
public int Counter { get; set; }
}
您可以标记计数器
然后作为并发令牌。使用Fluent API,它是:
You could mark the Counter
then as a concurrency token. With Fluent API it is:
modelBuilder.Entity<SomeEntity>()
.Property(s => s.Counter)
.IsConcurrencyToken();
然后您可以递增或递减 Counter
例如,像这样:
Then you can increment or decrement the Counter
for example like so:
public void IncDecCounter(int someEntityId, bool dec)
{
using (var context = new MyContext())
{
var someEntity = context.SomeEntities.Find(someEntityId);
if (someEntity != null)
{
bool saveFailed;
do
{
saveFailed = false;
if (dec)
--someEntity.Counter;
else
++someEntity.Counter;
try
{
context.SaveChanges();
}
catch (DbUpdateConcurrencyException e)
{
saveFailed = true;
e.Entries.Single().Reload();
}
} while (saveFailed);
}
}
}
如果实体加载后
将失败,并出现 DbUpdateConcurrencyException
(在此示例中,使用 Find
可以是任何其他查询)与数据库中 Counter
的值不同时, UPDATE语句在数据库中执行,这意味着 Counter
同时已被另一个用户修改。从技术上讲,这是通过生成的UPDATE语句的扩展 WHERE
子句实现的,该子句不仅尝试根据ID进行过滤,而且还尝试根据 Counter的旧值进行过滤
,基本上类似: WHERE SomeEntityId = someEntityId AND Counter = oldCounterWhenTheEntityHasBeenLoaded
。
SaveChanges
will fail with a DbUpdateConcurrencyException
if the value of Counter
when the entity has been loaded (with Find
in this example, could be any other query) differs from the value of Counter
in the database when the UPDATE statement is executed in the database which would mean that the Counter
has been modified by another user in the meantime. Technically this is achieved by an extended WHERE
clause of the generated UPDATE statement that tries to filter not only by the Id but also by the old value of Counter
, basically something like: WHERE SomeEntityId = someEntityId AND Counter = oldCounterWhenTheEntityHasBeenLoaded
.
The catch
块从数据库中使用当前 Counter
值重新加载实体,下一个循环尝试增加或减少重新加载的值再次赋值,直到成功而没有并发冲突。
The catch
block reloads the entity with the current Counter
value from the database and the next loop tries to increment or decrement the reloaded value again until it succeeds without concurrency violation.
这篇关于如何在实体框架5中增加/减少多用户安全的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!