简体   繁体   中英

Add an additional value from LINQ

I have the following bit of code:

var checkRegisters = await Database.Client.Context.CheckRegister
            .Where(cr => cr.CheckingAccount == account 
                   && cr.CheckDate >= fromDate 
                   && cr.CheckDate <= toDate 
                   && cr.Void == "N" )
            .GroupBy(cr => cr.CheckNumber, 
                     cr => cr.Amount, (key, g) => 
                                          new { 
                                                CheckNumber = key, 
                                                Amount = g.Sum()
                                              })
            .OrderBy(c => c.CheckNumber)
            .ToListAsync();

I don't fully understand what it is doing besides returning me a list of CheckNumber and Amount. The CheckRegister table contains the column Payee and so does the corresponding modelBuilder from the EF:

entity.Property(e => e.Payee).HasColumnType("varchar(255)");

How can I add Payee to the list I'm returned?

What the code does:

Your database has a table that contains CheckRegisters . Every CheckRegister has at least properties CheckingAccount , CheckDate , Void , CheckNumber and Amount , and according to you it also has a property Payee :

So your code described step by step.

// 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 
                     && checkRegister.CheckDate >= fromDate 
                     && checkRegister.CheckDate <= toDate 
                     && 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();

Now your desired change: Add the Payees .

The problem is, that the returned data are CheckRegisters grouped by CheckNumber. Every Payee is per CheckRegister. If you make groups of CheckRegisters with the same CheckNumber you get several Payees with this CheckNumber:

CheckNumber | Payee | ...
    1       |   A
    2       |   B
    1       |   C
    2       |   C    // note: C  is used again
    1       |   D

If I make groups with same CheckNumber, you'll get:

group CheckNumber 1 [1, A], [1,C], [1,D]
group CheckNumber 2 [2, B], [2,C]

So every group may have more than one Employee. If that's ok with you, just omit the ElementSelector and Select the Employees in the 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(),
    });

I would add it to the object you're creating in GroupBy. So change line 3 like below

.GroupBy(cr => cr.CheckNumber, cr => cr.Amount, cr => cr.Payee, (key, g) => 
                              new { CheckNumber = key, Amount = g.Sum(), Payee = g.Payee})

Note that group by was only separating by Number and Amount, so if you also group by Payee you should expect the resulting list to be longer. This is also assuming that Payee is the name of the column in your table.

Add the new column to the group by:

var checkRegisters = await Database.Client.Context.CheckRegister
            .Where(cr => cr.CheckingAccount == account && cr.CheckDate >= fromDate && cr.CheckDate <= toDate && 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();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM