Visual Studio 2008 LINQ удаляет строки, которые не работают

#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);
        }
    }