Как мне отсоединить объекты в Entity Framework Code First?

Ответы:

156

Если вы хотите отсоединить существующий объект, следуйте советам @ Slauma. Если вы хотите загружать объекты без отслеживания изменений, используйте:

var data = context.MyEntities.AsNoTracking().Where(...).ToList();

Как упомянуто в комментарии, это не будет полностью отделять сущности. Они все еще прикреплены, и ленивая загрузка работает, но сущности не отслеживаются. Это следует использовать, например, если вы хотите загружать сущность только для чтения данных и не планируете их изменять.

Ладислав Мрнка
источник
3
@Ladislav: Это действительно, вероятно, то, что имел в виду Lol Coder. Я никогда не использовал и не думал об этом методе, хотя я часто загружаю списки объектов и располагаю контекстом сразу, что-то вроде using(ctx){ return ctx....ToList(); }. В таких случаях использование AsNoTracking()будет иметь смысл, потому что я бы избавился от ненужного заполнения контекста объекта. Я предполагаю, что это, вероятно, принесет пользу производительности и потреблению памяти, особенно для больших списков, верно?
Слаума
1
@ Слаума: Да, это имеет преимущество в производительности. Именно поэтому этот метод существует. Использование этого подхода в ObjectContext API немного сложнее.
Ладислав Мрнка
2
Это отключает отложенную загрузку?
Шон Маклин,
3
На самом деле это не отключит отложенную загрузку, а только отключит отслеживание изменений и улучшит производительность = объект все еще прикреплен. Я нашел его после ответа на этот вопрос, поэтому вы должны пометить @ Slauma как правильный ответ.
Ладислав Мрнка
1
Это то, что я хочу. Я хочу ленивую загрузку и возможность изменять только отдельную сущность.
Шон Маклин
255

Это вариант:

dbContext.Entry(entity).State = EntityState.Detached;
Slauma
источник
3
Могу ли я сделать это при получении объектов, которые возвращают IQueryable?
Шон Маклин,
1
@Lol Coder: Я не уверен, правильно ли я вас понимаю, но это entityдолжен быть материализованный объект типа, который является частью ваших классов моделей (Person, Customer, Order и т. Д.). Вы не можете напрямую передать IQueryable <T> в dbContext.Entry(...). Это вопрос, который вы имели в виду?
Слаума
9
@EladBenda: это зависит. Если вы хотите отсоединить объект, который уже присоединен к контексту, установите состояние в Detached. Если вы хотите загрузить объекты из БД, не привязывая их вообще к контексту (без отслеживания изменений), используйте AsNoTracking.
Слаума
1
Я нашел интересную проблему с этим методом. Даже если сущность может быть прокси-классом, отложенная загрузка не будет работать после того, как вы измените ее состояние на Detached.
kjbartel
4
@kjbartel: это ожидаемое поведение, поскольку у сущности нет связи с контекстом.
Рикардо Соуза