无法删除该对象,因为在实体框架5中的ObjectStateManager中找不到该对象

时间:2013-03-26 13:13:55

标签: c# entity-framework-5

我正在尝试使用EntityFramework 5删除对象但是我收到此错误。 无法删除该对象,因为在ObjectStateManager 中找不到该对象 我使用Remove()方法,因为DeleteObject()在EF5中不存在。 任何人都可以帮助我缺少什么吗?

这对删除

无效
localDb.Customers.Remove(new Customer() { CustomerId = id });
                localDb.SaveChanges();

我尝试从msdn将状态更改为Deleted。但在这里它给出了一个错误,说所有的字段都应该存在。是否有必要获取完整的记录然后删除?

var customer = new Customer(){ CustomerId = id };
                localDb.Customers.Attach(customer);

                localDb.Entry(customer).State = EntityState.Deleted;
                localDb.SaveChanges();

任何输入?

5 个答案:

答案 0 :(得分:26)

您可以从数据库中获取该行,然后将其删除,但这会导致两次往返数据库。

如果你想一次点击,你的第二个版本Attach将起作用 - 只要该实体尚未加载到上下文中。

您获得的错误是由在任何数据库写入之前运行的EF验证引起的。

您可以暂时将其关闭:

bool oldValidateOnSaveEnabled = localDb.Configuration.ValidateOnSaveEnabled;

try
{
  localDb.Configuration.ValidateOnSaveEnabled = false;

  var customer = new Customer { CustomerId = id };

  localDb.Customers.Attach(customer);
  localDb.Entry(customer).State = EntityState.Deleted;
  localDb.SaveChanges();
}
finally
{
  localDb.Configuration.ValidateOnSaveEnabled = oldValidateOnSaveEnabled;
}

答案 1 :(得分:7)

如果您从数据库中检索了对象,那么它已经附加到上下文中,因此您可以通过以下方式删除:

db.myTable.Remove(model);

<强>但
如果你只是通过邮件收到编辑或删除视图的模型或自己生成它以避免2次访问数据库,那么EF不知道它并且你得到上面一行的错误(..在ObjectStateManager中找不到..)所以你将其状态设置为&#34;已删除&#34;通过以下方式通知EF

//generate it yourself if not posted from edit/delete view
//var model = new Model { Id = 123 };

//set to delete
db.Entry(model).State = EntityState.Deleted;
db.SaveChanges();

答案 2 :(得分:2)

你能这样做吗?

var customer = localDb.Customers.Single(o => o.CustomerId == id);
localDb.Customers.Remove(customer);
localDb.SaveChanges();

答案 3 :(得分:0)

public T Delete<T>(T obj) where T : class
        {
            T existing = context.Set<T>().Find(GetKeys(obj, context));

            if (existing != null)
            {
                context.Set<T>().Remove(existing);
                context.SaveChanges();
                return existing;
            }
            return null;
        }

private object[] GetKeys<T>(T entity, DbContext context) where T : class
        {
            ObjectContext objectContext = ((IObjectContextAdapter)context).ObjectContext;
            ObjectSet<T> set = objectContext.CreateObjectSet<T>();
            var keyNames = set.EntitySet.ElementType
                                                        .KeyMembers
                                                        .Select(k => k.Name).ToArray();
            Type type = typeof(T);

            object[] keys = new object[keyNames.Length];
            for (int i = 0; i < keyNames.Length; i++)
            {
                keys[i] = type.GetProperty(keyNames[i]).GetValue(entity, null);
            }
            return keys;
        }

答案 4 :(得分:0)

I know this question is quite old but none of the above worked for me since i was deleting registers from more than one class/service at once and each one of them was instantiating it's own database connection context.

What i did to solve it was to send the first created context to the rest of the classes/services that where going to access the database.

For example, my serviceA was going to delete some of it's registers and call serviceB and serviceC to do the same with their registers.

I would then delete my registers on serviceA and pass as a parameter the context created on the serviceA to serviceB and serviceC.