Какую разницу имеет значение .AsNoTracking ()?

228

У меня есть вопрос, касающийся .AsNoTracking()расширения, так как это все совершенно новое и довольно запутанное.

Я использую контекст для запроса для веб-сайта.

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

Вот пример, который я сейчас делаю:

context.Set<User>().AsNoTracking()
// Step 1) Get user
context.Set<User>()
// Step 2) Update user

Это то же самое, что и выше, но удаление .AsNoTracking()из шага 1:

context.Set<User>();
// Step 1) Get user
context.Set<User>()
// Step 2) Update user

Шаги 1 и 2 используют один и тот же контекст, но происходят в разное время. Я не могу понять, есть ли какая-то разница. Поскольку Шаг 2 является обновлением, я полагаю, что оба все равно дважды попадут в базу данных.

Может кто-нибудь сказать мне, в чем разница?

dotnetnoob
источник

Ответы:

187

Разница в том, что в первом случае извлеченный пользователь не отслеживается контекстом, поэтому, когда вы собираетесь сохранить пользователя обратно в базу данных, вы должны присоединить его и правильно установить состояние пользователя, чтобы EF знал, что он должен обновить существующего пользователя. вместо того, чтобы вставить новый. Во втором случае вам не нужно этого делать, если вы загружаете и сохраняете пользователя с тем же экземпляром контекста, потому что механизм отслеживания обрабатывает это за вас.

Ладислав Мрнка
источник
1
Можем ли мы получить те же преимущества для анонимных классов в запросе выбора, например context.Users.Select (u => new {Name = u.Name})? Спасибо.
Дилхан Джаятилаке
6
@DilhanJayathilake: Анонимные классы не представляют саму сущность, поэтому у них нет отслеживания.
Ладислав Мрнка
1
Поскольку EF6 иногда неверно выводит ключ объекта в представлении, AsNoTracking () игнорирует ключ и, следовательно, является альтернативой ручному исправлению ключа (при условии, что другие преимущества ключа не требуются).
crokusek
4
Также обратите внимание, что самый большой эффект, который имеет AsNoTracking, заключается в том, что отложенная загрузка не будет работать
Дуглас Гаскелл
170

смотрите эту страницу Entity Framework и AsNoTracking

Что делает AsNoTracking

Entity Framework предоставляет ряд параметров настройки производительности, которые помогут вам оптимизировать производительность ваших приложений. Один из этих вариантов настройки есть .AsNoTracking(). Эта оптимизация позволяет вам Entity Frameworkне отслеживать результаты запроса. Это означает, что не Entity Frameworkвыполняется дополнительная обработка или хранение объектов, возвращаемых запросом. Однако это также означает, что вы не можете обновить эти объекты, не подключив их к графику отслеживания.

при использовании AsNoTracking можно добиться значительного прироста производительности

Moji
источник
11
Кажется, что выгоды иногда могут быть уравновешены: stackoverflow.com/questions/9259480/…
Fabrice
3
Мой прирост производительности при сложном запросе, загружающем отношения родитель-потомок с включением за один шаг, составил около 50%
Карл
53

Нет отслеживания запросов LINQ to Entities

Использование AsNoTracking () рекомендуется, когда ваш запрос предназначен для операций чтения. В этих сценариях вы возвращаете свои объекты, но они не отслеживаются вашим контекстом. Это обеспечивает минимальное использование памяти и оптимальную производительность

Pros

  1. Улучшена производительность по сравнению с обычными запросами LINQ.
  2. Полностью материализованные объекты.
  3. Проще всего написать с синтаксисом, встроенным в язык программирования.

Cons

  1. Не подходит для операций CUD.
  2. Некоторые технические ограничения, такие как: Шаблоны, использующие DefaultIfEmpty для запросов OUTER JOIN, приводят к более сложным запросам, чем простые операторы OUTER JOIN в Entity SQL.
  3. Вы все еще не можете использовать LIKE с общим сопоставлением с образцом.

Более подробная информация доступна здесь:

Вопросы производительности для Entity Framework

Entity Framework и NoTracking

NullReference
источник
34

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

Ссылки:

Ронни Оверби
источник
10

AsNoTracking () позволяет обойти требование «уникальный ключ на запись» в EF (явно не упоминается в других ответах).

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

Для этих случаев «ключ» может быть установлен для любого необнуляемого столбца, но тогда AsNoTracking () должен использоваться с каждым запросом, иначе записи (дублирующиеся по ключу) будут пропущены.

crokusek
источник
2
Просто чтобы подтвердить важность этого для Views, у меня есть запрос из view, который возвращает 7 уникальных записей при запуске через SSMS. При запуске через EF без модификатора AsNoTracking я получаю первую запись, три копии второй и три копии третьей. Чтобы исправить это, потребовалось немало невероятных царапин, и он использовал AsNoTracking, который это исправил!
Ade
У меня была точно такая же проблема при использовании Linq to Entities при запросе View без первичных ключей. Об AsNoTracking узнал только после полдня царапин на голове. Это сообщение на форуме ASP.Net привело меня к этому. forums.asp.net/t/…
red_dorian
6

Если у вас есть что-то еще, изменяющее БД (скажем, другой процесс), и вам нужно убедиться, что вы видите эти изменения, используйте AsNoTracking(), в противном случае EF может дать вам последнюю копию, которая была у вашего контекста, следовательно, было бы хорошо использовать новый контекст каждый запрос :

http://codethug.com/2016/02/19/Entity-Framework-Cache-Busting/

Эндрю Пэйт
источник