TGViewer
.NET Разработчик .NET Разработчик @netdeveloperdiary · 6.75K subscribers
Post #2973 2.52K
День 2472. #ЗаметкиНаПолях
AsNoTrackingWithIdentityResolution в EF
При работе с Entity Framework Core понимание поведения отслеживания изменений критически важно как для производительности, так и для согласованности данных. Про AsNoTracking() знают все, а вот его мощная альтернатива AsNoTrackingWithIdentityResolution() не так популярна.

Что такое AsNoTracking()?
По умолчанию EF Core отслеживает все сущности, возвращаемые запросами в трекере изменений. Отслеживание обеспечивает:
- автоматическое обнаружение изменений в сущностях;
- операции обновления без явного присоединения сущностей;
- разрешение идентификаторов (гарантируя наличие только одного экземпляра каждой сущности в памяти).

Однако отслеживание сопряжено с накладными расходами. При выполнении операций только чтения, когда не требуется обновлять данные, AsNoTracking() повышает производительность, полностью отменяя отслеживание изменений:
var customers = await context.Customers
.AsNoTracking()
.ToListAsync();


Проблема - дублирование экземпляров сущностей. Если трекер изменений не будет выполнять разрешение идентификаторов, в памяти может оказаться несколько экземпляров одной и той же сущности, например:
var orders = await context.Orders
.AsNoTracking()
.Include(o => o.Customer)
.Where(o => o.OrderDate > DateTime.Now.AddDays(-30))
.ToListAsync();

Если несколько заказов принадлежат одному и тому же клиенту, вы получите отдельные экземпляры Customer для каждого заказа, даже если они представляют одну и ту же запись в БД. Это означает:
- увеличение потребления памяти,
- возможность путаницы при сравнении сущностей,
- потерю ссылочной целостности в графе объектов.

AsNoTrackingWithIdentityResolution()
AsNoTrackingWithIdentityResolution() решает эту проблему, объединяя преимущества двух подходов:
- отсутствие отслеживания изменений (выигрыш в производительности),
- разрешение идентификаторов (гарантия единственности экземпляров сущностей).
var orders = await context.Orders
.AsNoTrackingWithIdentityResolution()
.Include(o => o.Customer)
.Where(o => o.OrderDate > DateTime.Now.AddDays(-30))
.ToListAsync();
// Теперь все заказы от одного клиента
// будут ссылаться на один экземпляр Customer в памяти


При этом EF Core:
- выполняет запрос без присоединения сущностей к трекеру изменений;
- сохраняет временную карту идентификации во время материализации запроса;
- гарантирует, что сущности с одинаковым ключом ссылаются на один и тот же экземпляр;
- удаляет карту идентификации после завершения запроса.
Т.е. что вы получаете разрешение идентификации во время выполнения запроса без дополнительных затрат на отслеживание изменений.

Также можно установить AsNoTrackingWithIdentityResolution() как поведение трекера по умолчанию:
protected override void OnConfiguring(
DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder
.UseSqlServer(connectionString)
.UseQueryTrackingBehavior(
QueryTrackingBehavior.NoTrackingWithIdentityResolution);
}


Когда использовать
1. Отслеживание по умолчанию:
- необходимо обновлять, удалять или отслеживать изменения сущностей;
- небольшие наборы результатов, где затраты на отслеживание незначительны;
- необходимо автоматическое обнаружение изменений.

2. AsNoTracking:
- операции только чтения;
- нет свойств навигации или связанных сущностей;
- максимальная производительность критически важна;
- результаты не содержат дублирующихся сущностей.

3. AsNoTrackingWithIdentityResolution:
- операции только чтения с include/join;
- требуется ссылочная целостность в графе объектов;
- запросы, возвращающие одну сущность несколько раз;
- требуется сравнивать сущности по ссылке.

Источник: https://bartwullems.blogspot.com/2025/10/understanding-asnotrackingwithidentityr.html
  • 👍 47
More from @netdeveloperdiary
  1. Sep 30, 2026Post #3356
  2. Sep 29, 2026Фото 3 (с) Анатолий Кулаков
  3. Sep 29, 2026День 2799. Конференция DotNext 2026. Часть 1 25 и 26 сентября в Москве прошла очередная ко…
  4. Sep 28, 2026День 2798. #Оффтоп Утиная Типизация в C# с Помощью Перехватчиков. Часть 2 Некоторое время…
  5. Sep 27, 2026День 2797. #ЗаметкиНаПолях #AI Рабочий процесс с Copilot для .NET. Окончание Начало Продол…
  6. Sep 26, 2026День 2796. #ЗаметкиНаПолях #AI Рабочий процесс с Copilot для .NET. Продолжение Начало Три…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →