代码之家  ›  专栏  ›  技术社区  ›  Bastien Vandamme

如何用ef6实现乐观并发锁?

  •  1
  • Bastien Vandamme  · 技术社区  · 6 年前

    我有一个问题,混合了sqlserver、实体框架和webapi。

    我需要管理一个序列号数据库。为此,我在sqlserver中创建了一个序列表。我先用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的datacontext中更新我的CreateDate和ModifyDate。我覆盖SaveChange。

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

    这段代码在一个webservice后面,所以在同一时刻执行这段代码的两个请求可能返回相同的值。这不应该发生。

    因此SaveChanges()方法还必须检查我保存的内容是否被read()之后的另一个线程安全。

    1 回复  |  直到 6 年前
        1
  •  0
  •   usr    6 年前

    这当然是可以保证安全的。首先要注意的是,并发访问必须一个接一个。乐观并发在这里没有帮助。

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

    1. 使用 RepeatableRead 交易。这将导致死锁,您可以通过重试来解决。重新尝试是安全的,并保证取得进展。
    2. 将行作为事务中的第一个操作进行U-lock。实体框架无法直接执行此操作,因此需要手动SQL。正确的锁定提示是 UPDLOCK, HOLDLOCK, ROWLOCK .