Объект нельзя удалить, поскольку он не был найден в ObjectStateManager в структуре сущности 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();
Любые входы?
Ответы
Ответ 1
Вы можете получить строку из базы данных, а затем удалить ее, но это приводит к 2 обратным переходам в базу данных.
Если вы хотите сделать это за один удар, ваша вторая версия с 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;
}
Ответ 2
Если вы извлекли объект из базы данных, то он уже привязан к контексту, чтобы вы могли удалить его:
db.myTable.Remove(model);
но
если вы только что получили модель от редактирования или удаления представления по почте или сгенерировали ее самостоятельно, чтобы избежать 2 поездок в базу данных, тогда EF не знает об этом, и вы получите ошибку с указанной выше строкой (... не найденной в ObjectStateManager..), поэтому вы установите для своего состояния значение "Удалено", чтобы сообщить 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();
Ответ 3
Можете ли вы просто сделать это?
var customer = localDb.Customers.Single(o => o.CustomerId == id);
localDb.Customers.Remove(customer);
localDb.SaveChanges();
Ответ 4
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;
}
Ответ 5
Я знаю, что этот вопрос довольно старый, но ни один из вышеперечисленных не работал у меня, так как я удалял регистры из более чем одного класса/службы сразу, и каждый из них создавал экземпляр собственного контекста подключения к базе данных.
Что я сделал для его решения, так это отправить первый созданный контекст в остальные классы/службы, которые будут обращаться к базе данных.
Например, мой serviceA
собирался удалить некоторые из его регистров и вызвать serviceB
и serviceC
, чтобы сделать то же самое с их регистрами.
Затем я бы удалил свои регистры на serviceA
и передал в качестве параметра контекст, созданный на serviceA
до serviceB
и serviceC
.