2009-02-02 2 views
39

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

В Entity Framework , единственный способ, чтобы удалить объект данных, кажется,

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

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

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

+2

есть способ сделать это приятно и в целом: http://j.mp/f0x0Bh – BritishDeveloper

+0

@BritishDeveloper: Интересно! Тем не менее, после того, как этот вопрос был задан, я понял, что часто возникают причины для получения сущности, по крайней мере, если есть отношения с внешним ключом. –

+0

Возможный дубликат [Как удалить объект по идентификатору с каркасом сущности) (http://stackoverflow.com/questions/2471433/how-to-delete-an-object-by-id-with-entity-framework) –

ответ

19

Стоит знать, что 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

Этот ответ идет непосредственно к тому, что хотел бы сделать ассер, и должен быть помечен как принятый ответ. Другие решения, такие как создание объекта из ничего, менее оптимальны. Также проверьте это http://msdn.microsoft.com/en-us/library/ee358769.aspx – mare

+17

Почему вы вызываете SaveChanges после ExecuteStoreCommand? – epotter

+7

Magic string! Тьфу. – mayu

8

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

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

+3

Как насчет использования хранимой процедуры? –

4

Извиняюсь заранее, но я на вопрос своей цели.

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

DELETE FROM FOO 
WHERE ID = 1234 

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

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

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

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

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

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

+1

Это идеальная цель, если ваши объекты никогда не изменяются в течение срока их службы и/или вашего запроса, чтобы НАЙТИ объекты, которые нужно удалить, подразумевает, что все свойства, которые вы будете проверять, в любом случае уже имеют правильное значение. –

4

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

Блог статьи на Deleting without Fetching

3
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 и т.д.).

Имейте также взгляд here на общую функцию, если вы чувствуете, что-то причудливо.

+0

Это лучший способ (я называю это с использованием объекта-заполнителя), но он страдает от тех же проблем с параллелизмом, которые поднимает Stuntz ниже. – dansan

3

С Entity Framework 5 есть Entity Framework Extended Library. Доступно на NuGet. Тогда вы можете написать что-то вроде:

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

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

+0

Это невероятная библиотека! благодаря –

4

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

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