简体   繁体   中英

Dynamic grouping based on filters in Linq

I have two filters. One is to group by month,year,day and the other filter is to select if someone wants to group by product or company. There can be more filters as well. Now in the start I wrote if else for specific conditions like below.

List<IGrouping<String, TopItemReportData>> GroupedData = new List<IGrouping<String, TopItemReportData>>();

if (filters.DateBy.ToLower().Replace(" ", "") == "yearlyreport")
    GroupedData = topsalesQueryable.GroupBy(x => x.SalesDate.Year.ToString()).OrderByDescending(x => x.Sum(y => y.SellingQuantity)).Skip((filters.CurrentPage - 1) * filters.RecordsPerPage).Take(filters.RecordsPerPage).ToList();
else if (filters.DateBy.ToLower().Replace(" ", "") == "monthlyreport")
    GroupedData = topsalesQueryable.GroupBy(x => x.SalesDate.Month.ToString()).OrderByDescending(x => x.Sum(y => y.SellingQuantity)).Skip((filters.CurrentPage - 1) * filters.RecordsPerPage).Take(filters.RecordsPerPage).ToList();
else
    GroupedData = topsalesQueryable.GroupBy(x => x.SalesDate.Date.ToString()).OrderByDescending(x => x.Sum(y => y.SellingQuantity)).Skip((filters.CurrentPage - 1) * filters.RecordsPerPage).Take(filters.RecordsPerPage).ToList();

if (filters.GroupBy.ToLower().Replace(" ", "") == "variantoption")
    GroupedData = topsalesQueryable.GroupBy(x => (x.VariantId).ToString()).OrderByDescending(x => x.Sum(y => y.SellingQuantity)).Skip((filters.CurrentPage - 1) * filters.RecordsPerPage).Take(filters.RecordsPerPage).ToList();
else if (filters.GroupBy.ToLower() == "product")
    GroupedData = topsalesQueryable.GroupBy(x => (x.ProductId).ToString()).OrderByDescending(x => x.Sum(y => y.SellingQuantity)).Skip((filters.CurrentPage - 1) * filters.RecordsPerPage).Take(filters.RecordsPerPage).ToList();

But this won't work as now I have to group by both year and product at the same time based on selected filter values. So I don't know what to replace string by as compiler give error when I try to do this:

GroupedData = topsalesQueryable.GroupBy(x => new {x.SalesDate.Year.ToString(),x.ProductId.ToString()}).OrderByDescending(x => x.Sum(y => y.SellingQuantity)).Skip((filters.CurrentPage - 1) * filters.RecordsPerPage).Take(filters.RecordsPerPage).ToList();

that anonymous type member must be declared with a member assignment. My question is how to get rid of if else and how to solve this error

What you want is just a single string with both the year, and the product id.

We have a very simple way to create that:

string.Format("{0:0000}|{1:000000}", x.SalesDate.Year, x.ProductId)

The zeros after the colons get the size of the field, in case ProductId vary in length.

The whole thing (cleaned up a bit) would be:

void Main()
{
    var filters = new Filters();
    var topsalesQueryable = new List<TopItemReportData>();
    var TopItemReportData = new List<TopItemReportData>();
    IEnumerable<IGrouping<String, TopItemReportData>> tempGroupedData;

    var dateBy = filters.DateBy.ToLower().Replace(" ", "");
    var groupBy = filters.GroupBy.ToLower().Replace(" ", "");


    if ( dateBy  == "yearlyreport")
    {
        if (groupBy ==  "product")
            tempGroupedData = TopItemReportData
                               .GroupBy(x =>string.Format("{0:0000}|{1:000000}",
                                         x.SalesDate.Year, x.ProductId));
        else
           tempGroupedData = TopItemReportData.GroupBy(x => x.SalesDate.Year.ToString());
    }
    else if (dateBy == "monthlyreport")
        tempGroupedData = topsalesQueryable.GroupBy(x => x.SalesDate.Month.ToString());
    else
        tempGroupedData = topsalesQueryable.GroupBy(x => x.SalesDate.Date.ToString());

    if (groupBy == "variantoption")
        tempGroupedData = topsalesQueryable.GroupBy(x => x.VariantId.ToString());
    else if (groupBy == "product")
        tempGroupedData = topsalesQueryable.GroupBy(x => x.ProductId.ToString());

    var GroupedData = tempGroupedData
                            .OrderByDescending(x => x.Sum(y => y.SellingQuantity))
                            .Skip((filters.CurrentPage - 1) * filters.RecordsPerPage)
                            .Take(filters.RecordsPerPage)
                            .ToList();
}

class Filters
{
    public string DateBy;
    public string GroupBy;
    public int CurrentPage;
    public int RecordsPerPage;

    public Filters()
    {
        DateBy = "Yearly Report";
        GroupBy = "variantoption";
    }

}

class TopItemReportData
{
    public DateTime SalesDate;
    public int SellingQuantity;
    public int VariantId;
    public int ProductId;
}

You'll still need to straighten out the if/elses, though I think the best way to to eliminate the DateBy property and just use GroupBy.

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