如何使用EF 6实现乐观并发锁定?

时间:2018-11-07 11:53:34

标签: c# concurrency entity-framework-6

我有一个将SQL Server,实体框架和Web API混合在一起的问题。

我需要管理一个序列号数据库。为此,我在SQL Server中创建了一个序列表。我首先使用EF6代码。

public class Sequence : ITrackingDate
{
    [Key]
    public string Name { get; set; }
    public long CurrentValue { get; set; }
    public long Increment { get; set; }
    public long MinimumValue { get; set; }
    public long MaximumValue { get; set; }
    public bool IsCycling { get; set; }
    public DateTime CreateDate { get; set; }
    public DateTime ModifyDate { get; set; }
}

ITrackingDate用于在EF的数据上下文中更新我的CreateDate和ModifyDate。我覆盖了SaveChange。

这应该像一个序列一样工作(例如在SQL Server 2012中),但是我想自己在一个特定的数据库中对其进行管理,因为我将不得不创建许多序列,并且其中大多数将带有我们仅拥有的更多数据。基本序列系统。我需要具备的一项功能是可以按范围更新序列。

var serial = context.Sequences.SingleOrDefault(y => y.Name == serialName);
                var firstValue = serial.CurrentValue + 1;
                var lastValue = serial.CurrentValue + range;
                serial.CurrentValue = lastValue;
                context.SaveChanges();

此代码位于Web服务后面,因此可能同时执行2个请求,同时执行此部分代码,则返回相同的值。这永远不会发生。

所以SaveChanges()方法还必须检查自read()以来其他线程不安全保存的内容。

1 个答案:

答案 0 :(得分:0)

当然可以确保此安全。首先要注意的是,并发访问必须必须一个接一个地进行。乐观并发在这里无济于事。

有两种解决这个问题的基本策略:

  1. 使用-j交易。这将导致死锁,您可以通过重试来解决。重试是安全的,可以保证取得进展。
  2. 将行锁定为交易中的第一个操作。实体框架无法直接执行此操作,因此您需要手动SQL。正确的锁定提示为time make -j2 clean sleep 1 sleep 1 real 0m2.010s user 0m0.000s sys 0m0.004s