Я прочитал статью о методе AsNoTrackingWithIdentityResolution() и о том, что это способ разрешения личности без отслеживания, и что при его использовании в фоновом режиме запускается средство отслеживания изменений, отличное от средства отслеживания контекста, для разрешения объектов, на которые они ссылаются. одну и ту же строку в один экземпляр.
Я попытался проверить это, выполнив следующий код, но экземпляры не были разрешены в один экземпляр.
// Initially the table is empty
Employee emp1 = new Employee()
{
FirstName = "name1",
LastName = "name2",
Salary = 11111
};
context.Add(emp1);
context.SaveChanges();
Employee emp2 = (from e in context.Employees
where e.FirstName == "name1"
select e).SingleOrDefault();
// Identity resolution takes place
Console.WriteLine(emp1 == emp2); // True
Employee emp3 = (from e in context.Employees
where e.FirstName == "name1"
select e).AsNoTrackingWithIdentityResolution().SingleOrDefault();
// Expected to give True due to using AsNoTrackingWtihIdentityResolution()
Console.WriteLine(emp1 == emp3); // but found False
Employee emp4 = (from e in context.Employees
where e.FirstName == "name1"
select e).AsNoTrackingWithIdentityResolution().SingleOrDefault();
// Also no identity resolution happened
Console.WriteLine(emp4 == emp3); // False
Эталонное сравнение давало результат только тогда, когда два сравниваемых экземпляра (которые были разрешены в один экземпляр) отслеживались средством отслеживания изменений контекста, в то время как другие экземпляры не были разрешены в один экземпляр. Я использую ядро EF 8.0.2.
А сейчас:





AsNoTrackingWithIdentityResolution не используйте кэшированные (отслеживаемые) объекты, и ваши тесты неверны.
Этот режим работает только в области запроса. Он повторно использует объекты, загруженные директивой Include, для исправления свойств навигации и не создает дубликаты объектов одного типа и с одинаковыми ключами. Поэтому он и называется WithIdentityResolution.
Например, если у вас есть следующие классы:
class Employee
{
public int Id { get; set; }
public ICollection<Order> Orders { get; set; }
}
class Orders
{
public int Id { get; set; }
public int EmployeeId { get; set; }
public Employee Employee { get; set; }
}
И запрос:
var result = context.Employees
.Include(e => e.Orders)
.ThenInclude(o => o.Employee) // can be omitted, just shows what we are trying to load
.AsNoTrackingWithIdentityResolution();
Это означает, что у каждого загруженного сотрудника будут заказы с инициализированным навигационным свойством Employee с одной и той же ссылкой с использованием разрешения идентификаторов.
Тот же запрос без .ThenInclude(o => o.Employee) также должен инициализировать свойство Employee Orders, поскольку сотрудники загружаются в запрос, а разрешение идентификации может найти их в области запроса для инициализации.
Использование всего лишь AsNoTracking() создаст экземпляр для каждого нового объекта «Сотрудник» Order.
IOW, этот метод полезен, если вы загружаете большой граф объектов, он может уменьшить использование памяти и сложность запросов.
Да, более простым примером будет получение заказов из context.Orders и включение сотрудников. При использовании
AsNoTrackingкаждая сущность сотрудника будет отдельным объектом, даже если они указывают на одну и ту же строку в БД.AsNoTrackingWIthIdentityResolutionбудет гарантировать, что всем ссылкам на одного и того же сотрудника в заказах будет присвоена одна и та же ссылка на объект сотрудника. Ключевым моментом, как вы отметили, является то, что он применяется только в рамках этого одного запроса. Если ОП хочет иметь ссылки между запросами, ему следует использовать запрос отслеживания.