简体   繁体   中英

How to query / transform the data into the desired format

I wonder if anyone can help me to transform the below data (from a database) into List.:

Lorryid productid qtytype Qty iscomment comment
1 4090 3 2 f
1 4153 3 1 f
1 4153 3 1 f
1 4153 3 1 f
1 4153 3 1 f
1 4153 3 1 f
1 31068 3 2 f
1 31069 3 2 f
1 31173 3 2 f
2 17 0 1.000 f
2 150 3 6.000 f
2 216 3 6.000 f
2 278 2 1.020 f
2 398 2 1.125 f
2 398 2 1.090 f
2 398 2 0 t MUST BE RIPE
2 431 2 3.000 f
2 436 3 1.000 f
2 446 0 1 f
2 446 2 3.045 f
2 451 3 2.000 f
2 457 3 1.000 f
2 458 3 4.000 f
2 478 3 1.000 f
2 510 2 1.140 f
2 518 3 3.000 f
2 518 3 4.000 f
2 550 2 1.170 f
2 550 3 1.000 f

Into the below object.

public class View
{
  public List<LorryLoading> Report
}

public class LorryLoading
{
  public int LorryId
  public List<Product> Product
}

public class Product
{
  public int ProductId
  public decimal Qty0 sum(Quantity) WHERE QtyType = 0
  public decimal Qty2 sum(Quantity) WHERE QtyType = 2
  public decimal Qty3 sum(Quantity) WHERE QtyType = 3
  public List<string> Comments
}

Is it possible to do with a single projection? Having problems on assigning lists.

Also, any links where I can learn such transformations? The examples I've found so far are rather simple or poorly explained.

What You're asking is a transformation, so there is no simple projection. You can probably do it with a super complicated statement which will make Your colleague change job when they have to maintain :) my suggestion is to not try to impress campus but focus on clean code:

var lorryLoadingReport = new List<ReportData>();
//Presume you already have data into a transport object and know how to read that, as it wasn't your question

var view = new View
{
    Report = new List<LorryLoading>()
};
var listOf = new List<Product>();
        
//Lets not over complicate our mind, just keep it simple, let's get the products and the lorries
var productsList = lorryLoadingReport.Select(x => x.ProductId).ToList();
var lorriesList = lorryLoadingReport.Select(x => x.LorryId).ToList();
foreach (var lorry in lorriesList)
{
    //We'll need an entry even if the list will be empty
    var lorryLoading = new LorryLoading
    {
        LorryId = lorry,
        Product = new List<Product>()
    };

    //Get the respective subset
    var lorryLoadingReportPerLorry = lorryLoadingReport.Where(l => l.LorryId == lorry);
    if (lorryLoadingReportPerLorry.Any())
    {
        foreach (var productId in productsList)
        {
            //And add a product with all 4 sums iteratively
            var p = new Product
            {
                ProductId = productId,
                Comments = new List<string>()
            };
            var commentsList = lorryLoadingReport.Where(x => x.ProductId == productId && x.IsComment == "t").Select(s => s.Comment).ToList();
            if(commentsList.Any())
                p.Comments.AddRange(commentsList);
            p.Qty0 = lorryLoadingReport.Where(x => x.Qty == 0).Sum(y => y.Qty);
            p.Qty2 = lorryLoadingReport.Where(x => x.Qty == 2).Sum(y => y.Qty);
            p.Qty3 = lorryLoadingReport.Where(x => x.Qty == 3).Sum(y => y.Qty);

            lorryLoading.Product.Add(p);
        }
    }    
    view.Report.Add(lorryLoading);
}

You can use Linq's Aggregate to do a custom aggregation. This is slightly more complex as you have a double aggregation going on here.

Note that this will probably only work with Linq-to-Objects.

var report = data
    .GroupBy(row => row.Lorryid)
    .Select(l => new LorryLoading {
        LorryId = l.Key,
        Product = l
            .GroupBy(row => row.productid)
            .Select(p => p.Aggregate(
                new Product {ProductId = p.Key},  // this is the starting object
                (prod, row) => {                  // this aggregates it up
                    if(comment != null)
                        prod.Comments.Add(row.comment);
                    if(QtyType == 0)
                        prod.Qty0 += row.Quantity;
                    else if(QtyType == 2)
                        prod.Qty2 += row.Quantity;
                    else if(QtyType == 3)
                        prod.Qty3 += row.Quantity;
                })
            .ToList()
     }).ToList();

var view = new View {Report = report};

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