我正在使用实体框架来填充网格控件。有时当我进行更新时,我得到以下错误:
存储更新、插入或删除语句影响了意外的行数(0)。实体可能在加载实体后已被修改或删除。刷新ObjectStateManager条目。
我不知道怎么复制这个。但这可能和我更新的时间间隔有关系。有人见过这个吗,或者有人知道错误消息指的是什么吗?
编辑:不幸的是,我不再有自由重现我在这里遇到的问题,因为我离开了这个项目,不记得我最终是否找到了解决方案,是否有其他开发人员修复了它,或者是否我绕过了它。因此我不能接受任何回答。
我正在使用实体框架来填充网格控件。有时当我进行更新时,我得到以下错误:
存储更新、插入或删除语句影响了意外的行数(0)。实体可能在加载实体后已被修改或删除。刷新ObjectStateManager条目。
我不知道怎么复制这个。但这可能和我更新的时间间隔有关系。有人见过这个吗,或者有人知道错误消息指的是什么吗?
编辑:不幸的是,我不再有自由重现我在这里遇到的问题,因为我离开了这个项目,不记得我最终是否找到了解决方案,是否有其他开发人员修复了它,或者是否我绕过了它。因此我不能接受任何回答。
当前回答
我今天遇到了一个类似的问题,我将在这里记录它,因为它不完全是乐观并发错误。
我正在将一个旧系统转换为一个新的数据库,它有几千个实体,我必须把它们脚本转移到新系统。然而,为了帮助理智,我选择保持原始的唯一id,所以是注入到新对象,然后尝试保存它。
我遇到的问题是,我使用MVC脚手架来创建基本存储库,他们在他们的UpdateOrInsert方法中有一个模式,基本上是在添加新实体或将其状态更改为modified之前检查是否设置了Key属性。
因为设置了Guid,所以它试图修改数据库中实际上不存在的行。
我希望这能帮助到其他人!
其他回答
我今天遇到了一个类似的问题,我将在这里记录它,因为它不完全是乐观并发错误。
我正在将一个旧系统转换为一个新的数据库,它有几千个实体,我必须把它们脚本转移到新系统。然而,为了帮助理智,我选择保持原始的唯一id,所以是注入到新对象,然后尝试保存它。
我遇到的问题是,我使用MVC脚手架来创建基本存储库,他们在他们的UpdateOrInsert方法中有一个模式,基本上是在添加新实体或将其状态更改为modified之前检查是否设置了Key属性。
因为设置了Guid,所以它试图修改数据库中实际上不存在的行。
我希望这能帮助到其他人!
我将抛出这个,以防有人在并行循环中工作时遇到这个问题:
Parallel.ForEach(query, deet =>
{
MyContext ctx = new MyContext();
//do some stuff with this to identify something
if(something)
{
//Do stuff
ctx.MyObjects.Add(myObject);
ctx.SaveChanges() //this is where my error was being thrown
}
else
{
//same stuff, just an update rather than add
}
}
我把它改成如下:
Parallel.ForEach(query, deet =>
{
MyContext ctxCheck = new MyContext();
//do some stuff with this to identify something
if(something)
{
MyContext ctxAdd = new MyContext();
//Do stuff
ctxAdd .MyObjects.Add(myObject);
ctxAdd .SaveChanges() //this is where my error was being thrown
}
else
{
MyContext ctxUpdate = new MyContext();
//same stuff, just an update rather than add
ctxUpdate.SaveChanges();
}
}
不确定这是否是“最佳实践”,但它通过让每个并行操作使用自己的上下文来解决我的问题。
在SqlServer环境中调试这个问题的一种方法是使用SqlServer副本中包含的Sql Profiler,或者如果使用Express版本,可以通过下面的链接从CodePlex免费获得Express Profiler的副本:
表达分析器
通过使用Sql Profiler,您可以访问EF发送到DB的任何内容。就我而言,这相当于:
exec sp_executesql N'UPDATE [dbo].[Category]
SET [ParentID] = @0, [1048] = NULL, [1033] = @1, [MemberID] = @2, [AddedOn] = @3
WHERE ([CategoryID] = @4)
',N'@0 uniqueidentifier,@1 nvarchar(50),@2 uniqueidentifier,@3 datetime2(7),@4 uniqueidentifier',
@0='E060F2CA-433A-46A7-86BD-80CD165F5023',@1=N'I-Like-Noodles-Do-You',@2='EEDF2C83-2123-4B1C-BF8D-BE2D2FA26D09',
@3='2014-01-29 15:30:27.0435565',@4='3410FD1E-1C76-4D71-B08E-73849838F778'
go
我复制粘贴到Sql Server的查询窗口并执行它。可以肯定的是,尽管它运行了,但是0条记录受到了这个查询的影响,因此EF返回了错误。
在我的例子中,问题是由CategoryID引起的。
没有发送到数据库的ID EF标识的CategoryID,因此0条记录受到影响。
这并不是EF的错,而是在视图控制器中错误的空合并“??”语句,将无意义的内容发送到数据层。
检查你是否忘记了GridView中的“DataKeyNames”属性。 当在GridView中修改数据时,它是必须的
http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.gridview.datakeynames.aspx
对于那些使用AutoMapper的人 如果您正在更新一个实体,该实体具有指向另一个实体(或多个实体)的外键,请确保所有的外实体都将其主键设置为数据库生成(或对MySQL自动递增)。
例如:
public class BuyerEntity
{
[Key]
public int BuyerId{ get; set; }
public int Cash { get; set; }
public List<VehicleEntity> Vehicles { get; set; }
public List<PropertyEntity> Properties { get; set; }
}
Vehicles和Properties存储在不同于Buyers的表中。当你添加一个新的买家时,AutoMapper和EF会自动更新车辆和属性表,所以如果你没有在这些表上设置自动增量(就像我没有),那么你会看到来自OP的问题的错误。