1

在我正在为公司工作的数据库中,跟踪每个区域办事处的订单号。我有一个名为 [Company] 的表,其中每个区域办事处都有一条记录。此表有一个字段,其中包含该办公室的下一个可用订单号。所有订单都在单个 [Order] 表中创建。我意识到给定办公室的多个用户可能同时要求新订单。我已经为乐观并发设置了一切。[Company] 表有一个名为 RowModTracker 的列,用于并发目的(请参阅底部图像了解 EF 和 SQL 中的所有属性)。

在下面的代码中,我获取了地区办事处的记录,增加了具有订单号的字段并将副本放入本地变量中。然后我立即从桌子上省下来。我希望如果两个用户同时点击此方法,第一个保存的用户将获得一个有效的订单号。我希望第二个用户保存会得到一个乐观的并发错误,并且应该返回 null(这会导致提示要求他们重试)。用户告诉我,在过去的八个月里,他们确实收到过几次相同订单号的订单。直到他们去保存订单并且违反了对订单号的唯一约束时,才会发生消息和错误。

我显然不了解有关 EF 并发检查的基本知识,我希望有人可以向我展示。我编写了 GetNextOrderNumberAndUpdate 的测试版本,其中我使用上下文围绕第一个包裹了第二个,它确实产生了预期的并发错误。当两个不同的客户这样做时,它似乎不会发生。

 private int? TryToGetNextOrderNumber()
 {
     int? order_number;
      bool keep_trying = true;
      while (keep_trying)
      {
          order_number = _entityManager.GetNextOrderNumberAndUpdate();
          if (order_number != null) return order_number;
          keep_trying = KeepTryingForOrderNumberPrompt();
      }
      return null;
  }


  public int? GetNextOrderNumberAndUpdate()
  {
     try
     {     
         using (var db_context = new HotEntities(EntityConnectionString))
         {                   
              var hss_company = db_context.Companies.Find(HssCompanyInUse.HssCompanyId);
              int? next_order_num = ++hss_company.NextOrderNum;
              db_context.SaveChanges();
              return next_order_num;
          }
       }
       catch (DbUpdateConcurrencyException)
       {
           return null;
       }
       catch (Exception ex)
       {
           return null; //actual code puts out an alert as well 
       }
  }

公司表的 EF5 数据模型视图

公司表的 SSMS 视图

我正在使用带有 .NET 4.5 的 Entity Framework 5 和 SQL Server 2008 R2。

编辑

测试版本看起来像这样,我已经省略了所有的 try/catch 东西,它和上面一样

//Test force a failure 
using (HotEntities test_context = new HotEntities(EntityConnectionString))
{
    var test_hss_company = test_context.Companies.Find(HssCompanyInUse.HssCompanyId);
    int? test_next_order_num = ++test_hss_company.NextOrderNum;  
    //======= Normal Code ============
    using (var db_context = new HotEntities(EntityConnectionString))
    {
        var hss_company = db_context.Companies.Find(HssCompanyInUse.HssCompanyId);
        var next_order_num = ++hss_company.NextOrderNum;
        db_context.SaveChanges();
        return next_order_num;
    }
    //======= End Normal Code ============

test_context.SaveChanges(); //DbUpdateConcurrencyException exception would get thrown here
} //end for test using
4

0 回答 0