#visual-studio-2008 #linq-to-entities
#visual-studio-2008 #linq-to-entities
Вопрос:
Я использую Visual Studio 2008 с .NET Framework 3.5.
Я пытаюсь сделать то, что, как я думал, будет простым удалением некоторых строк с использованием LINQ to entities.
У меня есть простая серверная часть базы данных SQL Server, и я использую Data Entity Framework для доступа к ней. Я ничего не сделал с поведением по умолчанию, созданным в EDMX.
Я пытаюсь выполнить следующий код:
myDB.Dispose();
myDB = new EChODatabaseConnection();
//get our equipment list of requested equipment
var OldEquip = from u in myDB.dbEquipmentRequestedSet
where u.iRequestID == requestID
select u;
myDB.DeleteObject(OldEquip);
myDB.SaveChanges();
Это попадает в базу данных.Удаляет Object (OldEquip) и выдает следующую ошибку:
«Объект не может быть удален, поскольку он не был найден в ObjectStateManager».
Я проверил, что в OldEquip что-то есть до выполнения строки кода.
Я добавил первые две строки кода (Dispose и new) на случай, если возникла проблема с предыдущим кодом.
РЕДАКТИРОВАТЬ dbEquipmentRequestedSet выглядит следующим образом:
iRequestID (in db an int)
sCode (in db a varchar(50))
SCodePrefix (in db a varchar(10))
Я использую составной первичный ключ, основанный на iRequestID и sCode.
ОТРЕДАКТИРУЙТЕ 2, чтобы уточнить, почти во всех случаях запрос OldEquip приведет к нескольким результатам.
Судя по ответам на данный момент, мне придется вручную просматривать каждую запись для удаления.
Есть ли более элегантное решение? Может быть, с помощью хранимой процедуры?
Ответ №1:
Звучит так, как будто вы хотите удалить кратные числа. Попробуйте это:
var OldEquip = (from u in myDB.dbEquipmentRequestedSet
where u.iRequestID == requestID
select u)
.ToList();
foreach(var item in OldEquip)
{
myDB.DeleteObject(item);
}
Вероятная причина, если это DeleteObject
принимает объект, который должен быть сущностью, содержащейся в ObjectStateManager.В данный момент ваш код передал ему ObjectQuery<T>
, который не содержится в ObjectStateManager.
Подробнее в этом сообщении на форуме MSDN.
Комментарии:
1. Запрос сгенерирует более одного значения. добавляю правку, чтобы показать dbEquipmentRequestSet.
2. Да, запрос с вероятностью 99% приведет к множественному.
3. @Campbell: То есть нет способа удалить их все сразу? Я пытался выполнить хранимую процедуру для удаления и быстро ничего не добился :/
Ответ №2:
OldEquip
в этом случае имеет тип IQueryable. Вы можете удалять только реальные объекты, поэтому вам придется изменить инструкцию LINQ на что-то вроде:
var OldEquip = (from u in myDB.dbEquipmentRequestedSet
where u.iRequestID == requestID
select u).First();
или, если запрос возвращает несколько значений, просмотрите все результаты в IQueryable с помощью foreach
и удалите все элементы по отдельности.
Комментарии:
1. Я только что попробовал это с помощью ToList, и это выдает мне то же сообщение об ошибке: (
2. @Джон Стоун,
ToList != First
. Если вы хотите удалить несколько строк, вам придется перечислить их и вызвать DeleteObject несколько раз.3. Вы должны выполнить
foreach
и удалить каждый элемент в списке отдельно. Моя первоначальная формулировка была несколько неясной по этому поводу, извините за это.
Ответ №3:
У меня есть несколько методов расширения, которые я использую для удаления нескольких объектов одновременно, если вы хотите их использовать:
public static void DeleteAll(this ObjectContext context, IEnumerable<object> collection)
{
foreach (var item in collection.ToList())
{
context.DeleteObject(item);
}
}
public static void DeleteAll<TEntity>(this ObjectSet<TEntity> context, IEnumerable<TEntity> collection) where TEntity : class
{
foreach (var item in collection.ToList())
{
context.DeleteObject(item);
}
}