Ответ на вопрос, почему это происходит, это (после некоторых исследований) довольно интересный и хороший пример того, почему для его работы важно знать, как работает EF Core.
В целом, Linq работает над идеей отложенноговыполнение.Проще говоря, если я сделаю оператор Linq для конкретной строки, он может не быть оценен или выполнен до тех пор, пока данные «не понадобятся».Большую часть времени мы сокращаем это с помощью .ToList (), который вызывает немедленное выполнение.Общая идея здесь заключается в том, что иногда наборы данных не нужны (скажем, если исключение происходит до того, как оно будет оценено, но после того, как оно будет «загружено»).
EF Core делает еще один шаг вперед и связывает идею отложенного выполнения с оптимизацией базы данных.Если, например, я получаю подмножество данных из базы данных:
var result = _context.SomeTable.Where(x => x.name == "SomeValue");
Но позже все, что меня волнует, это размер набора данных:
return result.Count;
Вызов DB можетбыть оптимизирован до
select count(*) from SomeTable where name = "SomeValue";
вместо
select * from SomeTable where name = "SomeValue";
Точно так же, мой запрос был оптимизирован.Поскольку я все это связал до оценки, оптимизатор EF Core выбросил нужную мне таблицу.
Причина, по которой это работает:
var user = new Guid(id);
var userCustAffs = _data.UserCustomerAffiliation.Include(x => x.Customer)
.ThenInclude(x => x.Brand).Where(x =>
x.UserId.Equals(user)).ToList();
var result = userCustAffs.Select(p => p.Customer).ToList();
Это потому, что я принудительно выполняю запросэто что-то вроде
Select u.*, c.*, b.* from usercustomeraffiliation u,
inner join Customer c on u.customerid = c.id
inner join Brand b on c.brandid = c.id
where u.userid = 'userId';
, а затем удаляет объект клиента (и объект бренда под ним) в памяти.Было бы эффективнее иметь возможность генерировать запрос вроде:
Select c.*, b.* from Customer c on u.customerid = c.id
inner join Brand b on c.brandid = c.id
where c.id in (select u.customerid from usercustomeraffiliation u
where u.userid = 'userId');
Но это оптимизируется.