我有一个包含多个链接实体的实体框架项目.由于它被多个用户同时使用,我为可能被多个用户同时编辑的实体设置了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);
}
}
Run Code Online (Sandbox Code Playgroud)
model 是我想要添加到数据库的模型
编辑:如上所示,我修改了代码以忽略底层模型的更新.此外,我通过以下方式验证
ctx.Database.log = s => Debug.Write(s);
Run Code Online (Sandbox Code Playgroud)
只有一个insert语句被发送到数据库而不是另一个更新语句.
INSERT [dbo].[Samples]([IDSample], [ModificationDate], [IDUser])
VALUES (@0, @1, @2)
SELECT [RowVersion]
FROM [dbo].[Samples]
WHERE @@ROWCOUNT > 0 AND [IDSample] = @0 AND [ModificationDate] = @1
Run Code Online (Sandbox Code Playgroud)
如果我更新实体并且rowversion列不匹配,我会理解异常,但在这种情况下,它是一个全新的实体.有没有办法看看其中一个属性是否格式错误?
EDIT2:
我现在使用DateTime.Today代替DateTime.Now而不是仅仅修剪毫秒.看似在ModificationDate上的datetime2(4)存在一些问题.我已经确保将ModificationDate截断为4毫秒,因此不应该有解析错误.
EDIT3:
切换回DateTime.Now并修剪它停止工作的毫秒后,实体不再插入数据库.这可能是由于sql server在基于毫秒值匹配实体时出现问题.我执行了EF生成的SQL,如上所示,带有一些虚构的值,虽然在某些情况下查询没有返回rowversion值,但它仍然通过了.就实体框架而言,客户端会将此解释为0行的返回值,因此调用并发异常.(还应注意,ModificationDate和IDSample一起是实体的主键.)
Edit4:
我现在正在使用DateTime.Today,然后添加所需的精度,这对我有用.这可以标记为已解决.(Altough我原本预计EF可以自己处理日期时间格式转换:/)