在我正在处理的数据库中,公司会跟踪每个地区办事处的订单号。我有一个名为[公司]的表,每个区域办事处都有一条记录。此表有一个字段,用于保存该办公室的下一个可用订单号。所有订单都在单个[订单]表中创建。我意识到某个办公室的多个用户可以同时申请新订单。我已经为乐观并发设置了所有东西。 [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
}
}
我正在使用Entity Framework 5和SQL Server 2008 R2与.NET 4.5。
测试版本看起来像这样,我已经省略了与上面相同的所有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