我正在使用实体框架来填充网格控件。有时当我进行更新时,我得到以下错误:
存储更新、插入或删除语句影响了意外的行数(0)。实体可能在加载实体后已被修改或删除。刷新ObjectStateManager条目。
我不知道怎么复制这个。但这可能和我更新的时间间隔有关系。有人见过这个吗,或者有人知道错误消息指的是什么吗?
编辑:不幸的是,我不再有自由重现我在这里遇到的问题,因为我离开了这个项目,不记得我最终是否找到了解决方案,是否有其他开发人员修复了它,或者是否我绕过了它。因此我不能接受任何回答。
我正在使用实体框架来填充网格控件。有时当我进行更新时,我得到以下错误:
存储更新、插入或删除语句影响了意外的行数(0)。实体可能在加载实体后已被修改或删除。刷新ObjectStateManager条目。
我不知道怎么复制这个。但这可能和我更新的时间间隔有关系。有人见过这个吗,或者有人知道错误消息指的是什么吗?
编辑:不幸的是,我不再有自由重现我在这里遇到的问题,因为我离开了这个项目,不记得我最终是否找到了解决方案,是否有其他开发人员修复了它,或者是否我绕过了它。因此我不能接受任何回答。
当前回答
我还遇到了这个错误。问题原来是由我试图保存到的桌子上的触发器引起的。触发器使用了'INSTEAD OF INSERT',这意味着0行被插入到该表,因此出现了错误。幸运的是,在可能的情况下,触发器功能是不正确的,但我猜它可能是一个有效的操作,应该以某种方式在代码中处理。希望有一天这能帮助到别人。
其他回答
哇,很多答案,但我得到这个错误时,我做了一些稍微不同,没有人提到。
长话短说,如果您创建了一个新对象,并告诉EF它使用EntityState进行了修改。修改后,它将抛出这个错误,因为它还不存在于数据库中。这是我的代码:
MyObject foo = new MyObject()
{
someAttribute = someValue
};
context.Entry(foo).State = EntityState.Modified;
context.SaveChanges();
是的,这看起来很愚蠢,但它的出现是因为有问题的方法以前已经创建了foo,现在它只传递了someValue给它,并创建了foo自己。
很容易修复,只需改变EntityState。修改为EntityState。添加或更改整行为:
context.MyObject.Add(foo);
在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的错,而是在视图控制器中错误的空合并“??”语句,将无意义的内容发送到数据层。
当我在数据库中删除一些行(在循环中),并在同一表中添加新的行时,我得到了这个错误。
我的解决方案是,在每个循环迭代中动态地创建一个新的上下文
我有这个问题与Mvc身份注册新用户,而不是:
var result = await UserManager.CreateAsync(user);
我正在做:
var result = await UserManager.UpdateAsync(user);
这是乐观并发特性的副作用。
不是100%确定如何在实体框架中打开/关闭它,但基本上它告诉你的是,当你从数据库中获取数据时,当你保存你的更改时,其他人已经更改了数据(这意味着当你保存它时,0行实际上得到了更新)。在SQL术语中,它们的更新查询的where子句包含行中每个字段的原始值,如果0行受到影响,它就知道出错了。
它背后的思想是,你最终不会覆盖你的应用程序不知道发生了什么变化——它基本上是。net在所有更新中附带的一个小安全措施。
如果它是一致的,那么它很可能发生在您自己的逻辑中(例如:您实际上是在选择和更新之间的另一个方法中自己更新数据),但它可能只是两个应用程序之间的竞争条件。