【发布时间】:2015-05-15 08:52:03
【问题描述】:
我有一个包含多个链接实体的实体框架项目。由于它同时被多个用户使用,我为可能同时由多个用户编辑的实体设置了一个 RowVersion-Field。不幸的是,我现在每次尝试保存一个新实体时都会得到一个OptimisticConecurrencyException,该实体链接到一个已经存在的实体。
存储更新、插入或删除语句影响了意外数量的行 (0)。自加载实体后,实体可能已被修改或删除。有关理解和处理乐观并发异常的信息,请参阅 http://go.microsoft.com/fwlink/?LinkId=472540。
现在的问题是,这个错误并没有真正指出错误的真正位置。可能是同时修改了底层模型,新模型可能存在验证错误或其他原因。
我用来添加新实体的代码如下:
using (ctx = new DbContext())
{
try
{
ctx.Samples.Add(model);
ctx.SaveChanges();
}
catch (DbUpdateConcurrencyException ex)
{
LogManager.HandleException(ex.InnerException);
}
}
model 是我要添加到数据库的模型
编辑:如上所示,我修改了代码以忽略底层模型的更新。此外,我已通过以下方式验证:
ctx.Database.log = s => Debug.Write(s);
只有一个插入语句被发送到数据库,而不是一个额外的更新语句。
INSERT [dbo].[Samples]([IDSample], [ModificationDate], [IDUser])
VALUES (@0, @1, @2)
SELECT [RowVersion]
FROM [dbo].[Samples]
WHERE @@ROWCOUNT > 0 AND [IDSample] = @0 AND [ModificationDate] = @1
如果我要更新实体并且 rowversion 列不匹配,我会理解异常,但在这种情况下,它是一个全新的实体。有没有办法查看其中一个属性是否格式错误?
编辑2:
我现在不只是修剪毫秒,而是使用 DateTime.Today 而不是 DateTime.Now 。似乎在 ModificationDate 上的 datetime2(4) 存在一些问题。我已经确保 ModificationDate 被截断为 4 毫秒,所以应该没有解析错误。
编辑3:
切换回 DateTime.Now 并修剪毫秒后它停止工作并且实体不再插入数据库。这可能是由于 sql server 存在基于毫秒值匹配实体的问题。如上所示,我使用一些虚构的值执行了 EF 生成的 SQL,尽管在某些情况下查询没有返回 rowversion-value,但它通过了。在实体框架方面,客户端会将其解释为 0 行的返回值,因此调用并发异常。 (还需要注意的是,ModificationDate 和 IDSample 是实体的主键。)
编辑4:
我现在使用 DateTime.Today,然后添加所需的精度,这对我有用。这可以标记为已解决。 (尽管我希望 EF 可以自行处理日期时间格式转换:/)
【问题讨论】:
-
我认为验证不会触发
DbUpdateConcurrencyException -
如果模型有一个字段被截断,例如错误的 datetime2 格式,因此数据库不写入任何行并返回 0,它将触发并发异常。这是我已经发现的错误之一。
-
你的意思是它没有告诉你模型中的哪些字段与当前行不同?
-
是的。我不知道究竟是什么,或者更好地说是模型上的哪些字段导致了错误。
-
“标记为已解决”在此处不存在。最好的方法是写下你自己对问题的答案,详细说明解决方案,并在你能够这样做时接受它(我认为你需要两天时间才能使用该选项)。
标签: c# entity-framework entity-framework-6