我正在使用实体框架来填充网格控件。有时当我进行更新时,我得到以下错误:

存储更新、插入或删除语句影响了意外的行数(0)。实体可能在加载实体后已被修改或删除。刷新ObjectStateManager条目。

我不知道怎么复制这个。但这可能和我更新的时间间隔有关系。有人见过这个吗,或者有人知道错误消息指的是什么吗?

编辑:不幸的是,我不再有自由重现我在这里遇到的问题,因为我离开了这个项目,不记得我最终是否找到了解决方案,是否有其他开发人员修复了它,或者是否我绕过了它。因此我不能接受任何回答。


当前回答

以上的答案都没有完全涵盖我的情况和解决方案。

在MVC5控制器中抛出错误的代码:

        if (ModelState.IsValid)
        {
            db.Entry(object).State = EntityState.Modified; 
            db.SaveChanges(); // line that threw exception
            return RedirectToAction("Index");
        }

当我从Edit视图保存对象时,我收到了这个异常。它抛出它的原因是,当我回去保存它时,我修改了构成对象主键的属性。因此,将其状态设置为Modified对EF没有任何意义——它是一个新条目,而不是先前保存的条目。

你可以通过以下两种方法来解决这个问题:A)修改save调用来添加对象;B)在edit时不要更改主键。B)。

其他回答

在从模型优先改为代码优先之后,我开始得到这个错误。我有多个线程更新数据库,其中一些可能更新同一行。我不知道为什么我没有使用模型优先的问题,假设它使用不同的并发默认。

为了在一个地方处理它,知道它可能发生的条件,我在DbContext类中添加了以下重载:

using System.Data.Entity.Core.Objects;
using System.Data.Entity.Infrastructure;

public class MyDbContext: DbContext {
...
        public int SaveChanges(bool refreshOnConcurrencyException, RefreshMode refreshMode = RefreshMode.ClientWins) {
            try {
                return SaveChanges();
            }
            catch (DbUpdateConcurrencyException ex) {
                foreach (DbEntityEntry entry in ex.Entries) {
                    if (refreshMode == RefreshMode.ClientWins)
                        entry.OriginalValues.SetValues(entry.GetDatabaseValues());
                    else
                        entry.Reload();
                }
                return SaveChanges();
            }
        }
}

然后在任何适用的地方调用SaveChanges(true)。

我得到了同样的错误,因为PK的一部分是datetime列,而插入的记录使用了datetime。现在作为这一列的值。实体框架将以毫秒级精度插入值,然后以毫秒级精度查找刚刚插入的值。然而,SqlServer将该值舍入到秒精度,因此实体框架无法找到毫秒精度值。

解决方案是截断DateTime中的毫秒。在插入之前。

如果您试图插入一个唯一的约束情况,也会发生这种情况,即如果每个雇主只能有一种类型的地址,而您试图插入第二个具有相同类型的相同雇主的地址,您将遇到相同的问题。

OR

如果所有被赋值的对象属性,都被赋值与之前相同,也会发生这种情况。

        using(var db = new MyContext())
        {
            var address = db.Addresses.FirstOrDefault(x => x.Id == Id);

            address.StreetAddress = StreetAddress; // if you are assigning   
            address.City = City;                   // all of the same values
            address.State = State;                 // as they are
            address.ZipCode = ZipCode;             // in the database    

            db.SaveChanges();           // Then this will throw that exception
        }

对于那些使用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的问题的错误。

这件事刚刚发生在我身上。我正在运行Aurora (AWS MySQL),并试图将记录添加到表中。在模型中标记为[Key]的字段被映射到表中的一个自动递增字段…至少我是这么想的。它被设置为主键,但没有设置为自动递增。所以将它设置为自动递增解决了我的问题。