在我正在为公司工作的数据库中,跟踪每个区域办事处的订单号。我有一个名为 [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
}
}
我正在使用带有 .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