#c# #list #entity-framework #linq
#c# #Список #entity-framework #linq
Вопрос:
У меня есть следующий фрагмент кода:
var checkRegisters = await Database.Client.Context.CheckRegister
.Where(cr => cr.CheckingAccount == account
amp;amp; cr.CheckDate >= fromDate
amp;amp; cr.CheckDate <= toDate
amp;amp; cr.Void == "N" )
.GroupBy(cr => cr.CheckNumber,
cr => cr.Amount, (key, g) =>
new {
CheckNumber = key,
Amount = g.Sum()
})
.OrderBy(c => c.CheckNumber)
.ToListAsync();
Я не совсем понимаю, что он делает, кроме того, что возвращает мне список контрольных номеров и сумм. Таблица CheckRegister содержит столбец Payee, как и соответствующий ModelBuilder из EF:
entity.Property(e => e.Payee).HasColumnType("varchar(255)");
Как я могу добавить получателя платежа в список, который мне возвращается?
Ответ №1:
Что делает код:
В вашей базе данных есть таблица, которая содержит CheckRegisters
. У каждого CheckRegister
есть по крайней мере свойства CheckingAccount
, CheckDate
, Void
CheckNumber
и Amount
, и, по вашим словам, у него также есть свойство Payee
:
Итак, ваш код описан шаг за шагом.
// Take the complete table of CheckRegisters:
Database.Client.Context.CheckRegister
// from every checkRegister in this table (every row),
// keep only those checkRegisters that have a CheckingAccount value equal to account
// and a CheckDate value betwen fromData and toDate
// and a value for property Void equalt to "N"
.Where(checkRegister => checkRegister.CheckingAccount == account
amp;amp; checkRegister.CheckDate >= fromDate
amp;amp; checkRegister.CheckDate <= toDate
amp;amp; checkRegister.Void == "N" )
// Group all remaining CheckRegisters into groups with same checkNumber
// Each group will have a property Key which has the value of the common CheckNumber
.GroupBy(cr => cr.CheckNumber,
// ElementSelector: from every CheckRegister put only the amount in each grouop
checkRegister => checkRegister.Amount,
// ResultSelector: take every key (which we call checkNumber)
// and all Amounts of all CheckRegisters with this CheckNumber
// to make one new object:
(checkNumber, amountsFromCheckRegistersWithThisCheckNumber) => new
{
CheckNumber = key,
// To calculate property Amount: sum all amountsFromCheckRegistersWithThisCheckNumber
Amount = amountsFromCheckRegistersWithThisCheckNumber.Sum(),
})
// By now you have a sequence of objects, each with two properties:
// CheckNumber: a checkNumber used in the CheckRegisters that were left after the Where
// Amount: the sum of all Amounts of all CheckRegisters that have this CheckNumber
// Finally you do some Ordering, and convert the resulting elements into a list
.OrderBy(groupedItem => groupedItem.CheckNumber)
.ToListAsync();
Теперь желаемое изменение: добавьте Payees
.
Проблема в том, что возвращаемые данные являются контрольными регистрами, сгруппированными по контрольному номеру. Каждый получатель платежа соответствует контрольному регистру. Если вы создадите группы контрольных регистраторов с одинаковым контрольным номером, вы получите несколько получателей платежей с этим контрольным номером:
CheckNumber | Payee | ...
1 | A
2 | B
1 | C
2 | C // note: C is used again
1 | D
Если я создам группы с одинаковым контрольным номером, вы получите:
group CheckNumber 1 [1, A], [1,C], [1,D]
group CheckNumber 2 [2, B], [2,C]
Таким образом, в каждой группе может быть более одного сотрудника. Если вас это устраивает, просто опустите ElementSelector и выберите Employees в resultSelector
var result = Database.Client.Context.CheckRegister
.Where(...)
.GroupBy(cr => cr.CheckNumber,
// ResultSelector: take every key (which we call checkNumber)
// and all CheckRegisters with this CheckNumber
// to make one new object:
(checkNumber, checkRegistersWithThisCheckNumber) => new
{
CheckNumber = checkNumber,
// for Employees: Select property Employee, and convert them to a List
Employees = checkRegistersWithThisCheckNumber
.Select(checkRegister => checkRegister.Employee)
.ToList(),
// Amounts: select the Amounts and Sum
Amount = checkRegistersWithThisCheckNumber
.Select(checkRegister => checkRegister.Amount)
.Sum(),
});
Комментарии:
1. Намного ближе, и я думаю, что начинаю прозревать. Единственная ошибка — «key» после
CheckNumber = key
имени key не существует в текущем контексте. Спасибо за хорошо прокомментированный пример. Есть идеи по поводу ключевой ошибки?2. упс, введите после того, как я изменил идентификаторы на более описывающие имена. Исправлено
Ответ №2:
Я бы добавил его к объекту, который вы создаете в GroupBy. Поэтому измените строку 3, как показано ниже
.GroupBy(cr => cr.CheckNumber, cr => cr.Amount, cr => cr.Payee, (key, g) =>
new { CheckNumber = key, Amount = g.Sum(), Payee = g.Payee})
Обратите внимание, что group by разделяла только по номеру и сумме, поэтому, если вы также группируете по получателю платежа, вы должны ожидать, что результирующий список будет длиннее. Это также предполагает, что получатель платежа — это имя столбца в вашей таблице.
Комментарии:
1. Это и решение @Oscar M выдает ту же ошибку: аргументы типа для метода ‘Запрашиваются. GroupBy …..не может быть выведен из использования. Попробуйте явно указать аргументы типа.
2. Является ли cr объектом, возможно, типа CheckRegister? Можете ли вы добавить получателя платежа в поля этого объекта в виде строки, а затем повторить попытку кода?
3. Я думал, что у меня уже было это в последнем фрагменте кода в моем исходном сообщении с:
entity.Property(e => e.Payee).HasColumnType("varchar(255)");
это то, что Entity Framework создала из моей базы данных tables….at по крайней мере, я понимаю, как это работает4. Я должен добавить, что это ядро Entity Framework. Все еще не работает после того, как попробовал множество вариантов для Group By
Ответ №3:
Добавьте новый столбец в группу с помощью:
var checkRegisters = await Database.Client.Context.CheckRegister
.Where(cr => cr.CheckingAccount == account amp;amp; cr.CheckDate >= fromDate amp;amp; cr.CheckDate <= toDate amp;amp; cr.Void == "N" )
.GroupBy(cr => cr.CheckNumber, cr => cr.Amount, e => e.Payee , (key, g, p) => new { CheckNumber = key, Amount = g.Sum(), Payee = p})
.OrderBy(c => c.CheckNumber).ToListAsync();
Комментарии:
1. Это и решение @cyclopeanCity выдает ту же ошибку: аргументы типа для метода ‘Запрашиваются. GroupBy …..не может быть выведен из использования. Попробуйте явно указать аргументы типа.