DbSet.attach () заставил следующий запрос вернуть неверный результат - PullRequest
0 голосов
/ 22 сентября 2019

Допустим, эти User данные были записаны в базе данных ..

User {
   Id = 1,
   Name = "John",
   Job = "Programmer"
};

А позже я хочу обновить его имя.Итак, я выполняю эту команду

var entity = new User { Id = 1 };

_context.Users.Attach(entity);

entity.Name = "Jack";

await _context.SaveChangesAsync();

Наконец, я снова запрашиваю, чтобы увидеть обновление

var order = await _context.Users
                          .FirstOrDefaultAsync(x => x.Id == 1));

Но данные, которые я получил, странные ...

User {
   Id = 1,
   Name = "Jack",
   Job = null <----- this should not be null
};

похоже, что результат запроса приходит, когда _context отслеживает запись после вызова метода attach().

Любая, идея или что я должен сделать, чтобы предотвратить этот странный результат.

1 Ответ

0 голосов
/ 23 сентября 2019

Причина, по которой вы видите #null для задания, заключается в том, что объект, который DbContext возвратил вам в последнем запросе, был бы экземпляром, который вы инициировали и прикрепили к контексту.Когда вы вызываете SaveChanges со своей сущностью, она имеет идентификатор 1, имя «Джек» и задание #null.Отслеживание показало, что EF изменилось только имя, так что это все, что было указано в БД в операторе Update.

EF делает некоторые немного сомнительные вещи за кулисами, но когда вы выбираете сущность, она возвращает все, что у нее есть в кеше, если она доступна, перед загрузкой сущности из базы данных.Что может сбить с толку, так это то, что если вы профилируете против БД, вы увидите SELECT, поднятый против базы данных, но возвращаемая сущность будет отражать последнее кэшированное состояние, а не состояние базы данных.Чтобы обновить сущность, вы можете:

_context.Entity(user).Reload();

перезагрузить отслеживаемую сущность.или ...

_context.Entity(user).EntityState = EntityState.Detached;
user = _context.Users.Single(x => x.Id == 1);

... чтобы отсоединить сущность, которую вы обновили снова, чтобы заставить EF перезагрузить при запросе, или ...

user = _context.Users.AsNoTracking().Single(x => x.Id == 1);

... загрузить новую неотслеживаемуюссылка.

Как правило, при редактировании сущностей следует загружать сущности, применять изменения и сохранять, а не трюк Id + Attach.Идентификатор + Attach - это удобный хак для удаления сценариев или, возможно, массовых обновлений, но только в недолговечных DbContexts, чтобы эти отслеживаемые «частичные» сущности не возвращались снова другими запросами.

...