如何在实体框架中加入/解决多用户安全问题5

Nic*_*ckD 11 t-sql entity-framework

什么是增加或减少整数字段的干净,安全的方法.

我将sql server 2012与entityframework 5.x结合使用

我寻找相当于互锁的增量/减量.

Sla*_*uma 19

标准方法是使用乐观并发.

比如,你有一个简单的实体Counter,你想要增加或减少一个整数字段:

public class SomeEntity
{
    public int SomeEntityId { get; set; }
    public int Counter { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

您可以将Counterthen 标记为并发令牌.使用Fluent API,它是:

modelBuilder.Entity<SomeEntity>()
    .Property(s => s.Counter)
    .IsConcurrencyToken();
Run Code Online (Sandbox Code Playgroud)

然后你可以增加或减少Counter例如:

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);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

SaveChangesDbUpdateConcurrencyException如果Counter加载实体的时间(Find在本例中,可能是任何其他查询)与Counter在数据库中执行UPDATE语句时数据库中的值不同,则表示已经失败Counter了在此期间由另一个用户修改.从技术上讲,这是通过WHERE生成的UPDATE语句的扩展子句实现的,该子句不仅尝试过滤Id,而且过滤旧值Counter,基本上类似于:WHERE SomeEntityId = someEntityId AND Counter = oldCounterWhenTheEntityHasBeenLoaded.

catch块使用Counter来自数据库的当前值重新加载实体,并且下一个循环尝试再次递增或递减重新加载的值,直到它成功而没有并发冲突.