Обычно, если вы обнаруживаете, что выполняете внешнее левое соединение, за которым следует GroupBy, это потому, что вам нужны «элементы со своими подпунктами», например «Школы со своими учениками», «Клиенты со своими заказами», «Группы клиентов» со своими клиентами ", et c. Если вы хотите этого, рассмотрите возможность использования GroupJoin вместо «Join + DefaultIfEmpty + GroupBy»
Я более знаком с синтаксисом метода, поэтому я буду его использовать.
int merchantId = ...
var result = dbContext.CustomerGroups
// keep only the CustomerGroups from merchantId
.Where(customerGroup => customerGroup.MerchantId == merchantId)
.GroupJoin(dbContext.Customers, // GroupJoin with Customers
customerGroup => customerGroup.GroupId, // from every CustomerGroup take the GroupId
customer => customer.GroupId, // from every Customer take the GroupId
// ResultSelector:
(customerGroup, customersInThisGroup) => new // from every CustomerGroup with all its
{ // matching customers make one new object
GroupName = customerGroup.Key,
Quantity = customersInThisGroup.CustomerId, // ???
});
Словами:
Взять последовательность групп клиентов. Оставьте только те группы клиентов, которые имеют значение свойства MerchantId равным merchantId. Из каждой оставшейся CustomerGroup получите всех своих клиентов, сравнив CustomerGroup.GroupId с каждым Customer.GroupId.
Результатом является последовательность CustomerGroups, каждая со своими клиентами. Из этого результата (параметр ResultSelector) получите GroupName от клиента и количество от клиентов в этой группе.
Ваше утверждение было:
Quantity = customers.CustomerID,
Это не будет работать. Я уверен, что это не то, что вы хотите. Увы, ты забыл написать что хочешь. Я думаю, что это:
Quantity = customers.Count().
Но если вы хотите, чтобы CustomerId всех клиентов в этой группе клиентов:
// ResultSelector:
(customerGroup, customersInThisGroup) => new
{
GroupName = customerGroup.Key,
CustomerIds = customersInThisGroup.Select(customer => customer.CustomerId)
.ToList(),
);
Если вы хотите, вы можете использовать ResultSelector, чтобы получить "Группы клиентов с их клиенты ". Наиболее эффективным является выбор только тех свойств, которые вы фактически планируете использовать:
// ResultSelector:
(customerGroup, customersInThisGroup) => new
{
// select only the CustomerGroup properties that you plan to use:
Id = CustomerGroup.GroupId,
Name = CustomerGroup.Name,
... // other properties that you plan to use
Customers = customersInThisGroup.Select(customer => new
{
// again, select only the Customer properties that you plan to use
Id = customer.Id,
Name = customer.Name,
...
// not needed, you know the value:
// GroupId = customer.GroupId
});
Причина, по которой вы не выбираете внешний ключ Клиентов, - это эффективность. Если CustomerGroup [14] имеет 1000 клиентов, то для каждого клиента в этой группе значение GroupId будет равно [14]. Было бы напрасно посылать это значение [14] 1001 раз.