Home > Software design >  EF core Get Count and sum in one call
EF core Get Count and sum in one call

Time:12-05

Using Entity Framework core, can I get the total sum of the column and row count in one call? I have the following code, but I think there is a better way to do this.

TotalCostResponse result = new TotalCostResponse
{
    TotalCost = await dbContext.Transaction
        .Where(x => x.UserName == request.UserName
            && x.Date >= request.StartDate
            && x.Date <= request.EndDate)
        .SumAsync(x => x.Amount),

    TotalNumber = await dbContext.Transaction
        .Where(x => x.UserName == request.UserName
            && x.Date = request.StartDate
            && x.Date <= request.EndDate)
        .CountAsync()
};

So instead of calling dbContext two times, I need to make it in one call.

CodePudding user response:

var result = await dbContext.Transaction
    .Where(x => x.UserName == request.UserName
        && x.Date >= request.StartDate
        && x.Date <= request.EndDate)
    .GroupBy(x => 1)
    .Select(group => new TotalCostResponse
    {
        TotalCost = group.Sum(x => x.Amount),
        TotalNumber = group.Count()
    })
    .FirstOrDefaultAsync();

CodePudding user response:

Yes, you can get the total sum and row count in a single call to the database using the Sum and Count methods together in a LINQ query. Here is an example of how you could do this:

TotalCostResponse result = new TotalCostResponse
{
// Use the Sum and Count methods together in a LINQ query to get the total sum
// and row count in a single call to the database.
TotalCost = await dbContext.Transaction
    .Where(x => x.UserName == request.UserName
        && x.Date >= request.StartDate
        && x.Date <= request.EndDate)
    .Select(x => new
    {
        // Select the Amount column and use the Sum method to get the total sum.
        TotalCost = x.Amount.Sum(),
        // Use the Count method to get the row count.
        TotalNumber = x.Amount.Count()
    })
    // Use the SingleOrDefault method to get the first element of the query result.
    // If the query result is empty, this will return null.
    .SingleOrDefault(),

// If the query result is not null, set the TotalCost and TotalNumber properties
// of the TotalCostResponse object using the values from the query result.
// If the query result is null, these properties will remain uninitialized.
TotalCost = result?.TotalCost,
TotalNumber = result?.TotalNumber
};

Alternatively, you could use the Sum and Count methods in separate LINQ queries and then combine the results in memory, like this:

// Use the Sum method in a LINQ query to get the total sum.
decimal? totalCost = await dbContext.Transaction
.Where(x => x.UserName == request.UserName
    && x.Date >= request.StartDate
    && x.Date <= request.EndDate)
.SumAsync(x => x.Amount);

// Use the Count method in a LINQ query to get the row count.
int? totalNumber = await dbContext.Transaction
.Where(x => x.UserName == request.UserName
    && x.Date = request.StartDate
    && x.Date <= request.EndDate)
.CountAsync();

TotalCostResponse result = new TotalCostResponse
{
// Set the TotalCost and TotalNumber properties of the TotalCostResponse
// object using the values from the LINQ queries.
TotalCost = totalCost,
TotalNumber = totalNumber
};

Both of these approaches will allow you to get the total sum and row count in a single call to the database, which should be more efficient than making two separate calls like in your original code.

CodePudding user response:

Here is an example with one querry, There are certainly other ways tath you can find.

//In the select get only what you need, in your case only the Amount
var transactions = await this.dbContext.Transaction
               .Where(x => x.UserName == request.UserName
               && x.Date >= request.StartDate
               && x.Date <= request.EndDate)
               .Select(y => new
               {
                  Amount = y.Amount,
               }).ToListAsync();

//Calculating the data
var result = new TotalCostResponse
{
   TotalCost = transactions.Sum(x => x),
   TotalNumber = transactions.Count(),
}

//Dto model for the result
public class TotalCostResponse
{
   public decimal TotalCost { get; set; }
   public int TotalNumber { get; set; } 
}

  • Related