Как удалить объект из модели Entity Framework без его первой загрузки?

Я уверен, что я видел ответ на этот вопрос где-то, но поскольку я не мог найти его с помощью нескольких поисков в SO или google, я все равно прошу его снова...

В Entity Framework единственным способом удаления объекта данных является

MyEntityModel ent = new MyEntityModel();
ent.DeleteObject(theObjectToDelete);
ent.SaveChanges();

Однако этот подход требует, чтобы объект загружался, в этом случае, сначала в контроллер, только чтобы удалить его. Есть ли способ удалить бизнес-объект, ссылающийся только на его идентификатор?

Если есть более разумный способ использования выражений Linq или Lambda, это тоже хорошо. Основная цель, однако, состоит в том, чтобы избежать загрузки данных только для ее удаления.

Ответ 1

Стоит знать, что Entity Framework поддерживает как Linq для Entities, так и Entity SQL. Если вы обнаружите, что хотите удалить или обновить файлы, которые могут повлиять на многие записи, вы можете использовать эквивалент ExecuteNonQuery.

В Entity SQL это может выглядеть как

   Using db As New HelloEfEntities

        Dim qStr = "Delete " & _
                  "FROM Employee"
        db.ExecuteStoreCommand(qStr)
        db.SaveChanges()
    End Using

В этом примере db - мой ObjectContext. Также обратите внимание, что функция ExecuteStoreCommand принимает необязательный массив параметров.

Ответ 2

Я нашел этот пост, в котором говорится, что действительно нет лучшего способа удалить записи. Приведенное объяснение состояло в том, что все внешние ключи, отношения и т.д., Которые являются уникальными для этой записи, также удаляются, поэтому EF должен иметь правильную информацию о записи. Я озадачен тем, почему этого не может быть достигнуто без загрузки данных взад и вперед, но поскольку это не произойдет очень часто, я решил (на данный момент), что не буду беспокоиться.

Если у вас есть решение этой проблемы, не стесняйтесь сообщить мне =)

Ответ 3

Извиняюсь заранее, но я должен поставить под сомнение вашу цель.

Если вы удаляете объект, не читая его, вы не можете знать, изменил ли другой пользователь объект между временем, когда вы подтвердили, что хотите удалить объект и фактическое удаление. В "обычном старом SQL" это будет выглядеть так:

DELETE FROM FOO
WHERE ID = 1234

Конечно, большинство людей на самом деле этого не делают. Вместо этого они делают что-то вроде:

DELETE FROM FOO
WHERE ID = 1234
  AND NAME = ?ExpectedName AND...

Дело в том, что удаление должно завершиться неудачей (ничего не делать), если другой пользователь изменил запись в промежуточный период.

Благодаря этому, лучшему описанию проблемы, при использовании Entity Framework возможны два возможных решения.

  • В методе Delete существующий экземпляр сравнивает ожидаемые значения свойств и удаляет, если они одинаковы. В этом случае Entity Framework позаботится о написании оператора DELETE, который включает значения свойств.

  • Напишите хранимую процедуру, которая принимает как IDE, так и другие значения свойств и выполняет их.

Ответ 4

Есть способ обмануть загрузку объекта путем повторного вычисления EntityKey. Это выглядит немного взломанным, но может быть единственным способом сделать это в EF.

Статья в блоге Удаление без выборки

Ответ 5

Вы можете создать объект с тем же идентификатором и передать его удалению НО это полезно для простых объектов, если у вас сложные отношения, вам может понадобиться больше, чем

                var user = new User { ID = 15 };
                context.Entry(user).State = EntityState.Deleted;
                context.SaveChanges();

Ответ 6

var toDelete = new MyEntityModel{
    GUID = guid,
    //or ID = id, depending on the key
    };
Db.MyEntityModels.Attach(toDelete);
Db.MyEntityModels.DeleteObject(toDelete);
Db.SaveChanges();

Если ваш ключ содержит несколько столбцов, вам необходимо указать все значения (например, GUID, columnX, columnY и т.д.).

Ищите здесь для общей функции, если вы чувствуете что-то фантастическое.

Ответ 7

В Entity Framework 5 есть Расширенная библиотека Entity Framework. Доступно на NuGet. Затем вы можете написать что-то вроде:

context.Users.Delete(u => u.Id == id);

Он также полезен для массовых удалений.