tylkonachwile
tylkonachwile

Reputation: 2277

Group by in .net core 3.1

I am trying to group by 2 fields and than count rows of each status. I am using .NET core 3.1 and newest version of EF.

I am getting an error: The LINQ expression could not be translated. Either rewrite the query in a form that can be translated...

What I investigated so far is, when I get rid off predicate y.Count(x=>x.Status == "New") and just leave y.Count() it works fine.

Orders collection is just a mocked list of objects, in my real app it is a table in sql server.

//Rextester.Program.Main is the entry point for your code. Don't change it.
//Microsoft (R) Visual C# Compiler version 2.9.0.63208 (958f2354)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;

namespace Rextester
{
    public class Program
    {
        public static void Main(string[] args)
        {
            var orders = new List<Order>();
            orders.Add(new Order(){Year = 2020, Status = "New"});
            orders.Add(new Order(){Year = 2020, Status = "New"});
            orders.Add(new Order(){Year = 2020, Status = "Canceled"});
            orders.Add(new Order(){Year = 2020, Status = "Shipped"});            

            
            var result = await orders
                .GroupBy(x=> new {x.Year, x.Status})
                .Select(y => new 
                {   
                    Year = y.Key.Year,
                    NewCount = y.Count(x=>x.Status == "New"),
                    CanceledCount = y.Count(x=>x.Status == "Canceled"),
                    ShippedCount = y.Count(x=>x.Status == "Shipped")                          
                }).ToListAsync();
        }
    }
    public class Order
    {
        public int Year {get;set;}
        public string Status {get;set;}
    }
}

Expected result is:

Year: 2020, NewCount: 2

Year: 2020, CanceledCount : 1

Year: 2020, ShippedCount : 1

What am I doing wrong? How to correct this error to get desired output?

EDIT: This is my playground https://dotnetfiddle.net/v7IYmq

Upvotes: 0

Views: 87

Answers (1)

TsTeaTime
TsTeaTime

Reputation: 921

Can you try the following. You are already grouping by Year and Status. Status is part of your key so you can use that to your advantage. Then just count the records using y.Count()

using System;
using System.Collections.Generic;
using System.Linq;
                    
    public class Program
    {
        public static void Main(string[] args)
        {
            var orders = new List<Order>();
            orders.Add(new Order(){Year = 2020, Status = "New"});
            orders.Add(new Order(){Year = 2020, Status = "New"});
            orders.Add(new Order(){Year = 2020, Status = "Canceled"});
            orders.Add(new Order(){Year = 2020, Status = "Shipped"});            

            
            var result = orders
                .GroupBy(x=> new {x.Year, x.Status})
                .Select(y => new 
                {   
                    Year = y.Key.Year,
                    Status = y.Key.Status,
                    Count = y.Count()                      
                }).ToList();
            foreach (var item in result)
                {
                    Console.WriteLine(string.Format("{0} {1} {2}",item.Year,item.Status, item.Count));
                }
        }
    }
    public class Order
    {
        public int Year {get;set;}
        public string Status {get;set;}
    }

Upvotes: 1

Related Questions