简体   繁体   中英

Consolidating a datatable into a more readable format: C#, Entity Framework

I have a SQL table that is structured as follows:

The difficulty is that each order ID has a different line for different Detail and Type categories:

ID Order_ID Detail Type Amount
12 567888 Refund -100
13 222222 Charge 250
14 222222 Tax 10
15 222222 Fee Shipping -20
15 222222 Fee Handling -10

I am trying to consolidate this into a new Gridview in Winforms so that every Order_ID is represented on only one line:

ID ORDER_ID Charge Tax Fee
1 222222 250 10 -30

Here is what I have and I have made progress:

using (var context = new Sales_Entities())
{   
     // saleslist contains the entire original table filtered on the Charge
     var saleslist = context.Sales.Where(a => a.Type == "Charge").ToList();                                 
     dataGridView1.DataSource = saleslist;

     // add 2 new columns
     dataGridView1.Columns.Add("_Tax", "Tax");
     dataGridView1.Columns.Add("_Fees", "Fee");

     // new list that has only the tax lines with the order_id
     var taxlist = context.Sales.Where(a => a.Detail == "Tax").ToList();  

     // new list that has only the fee lines with the order_id                              
     var feelist = context.Sales.Where(a => a.Type  == "Fee").ToList();                                       

     // iterating over the datagrid because I am looking up the order_id and 
     foreach (DataGridViewRow row in dataGridView1.Rows)
     {
         // search for a tax associated with that order_id so iterate through the taxlist
         foreach (var tax_amount in taxlist)
         {
             // put that tax amount into a new column if the order_Id matches
             if (tax_amount.Order_ID.ToString() == row.Cells[1].Value.ToString())
             {
                 row.Cells[3].Value = tax_amount.Amount.ToString();
             }
         }
     }
 }

Notice that there are 2 fee lines for the order ID and I am having a hard time summing those 2 (because they apply to the same order ID) and place them in the new Fee column I have created.

THANK YOU Ricardo: I was also trying to pull an SKU column:

                    from sale in context.Sales
                    group sale by sale.Order_ID into byOrder
                    select new
                    {
                        Order_ID = byOrder.Key,
                        SKU = (from sale in byOrder select sale.SKU.ToString()),
                        Charge = (from sale in byOrder where sale.Payment_Type == "Product charges                                   " select sale.Amount).Sum(),
                        Tax = (from sale in byOrder where sale.Payment_Detail == "Product Tax                                       " select sale.Amount).Sum(),
                        Fee = (from sale in byOrder where sale.Payment_Detail == "FBA Pick & Pack Fee                               " ||
                               sale.Payment_Detail == "Referral Fee on Item Price                        " select sale.Amount).Sum()
                        
                    };

                dataGridView1.DataSource = consolidated.ToList();

But that did not work. Does anyone have a resource that explains LINQ language and c#. There are many I know but any that you found especially helpful. I feel like I am just stumbling through the syntax.

I also tried:

SKU = (from sale in byOrder where sale.SKU.ToString() != null select sale.SKU)

and

SKU = (from sale in byOrder where sale.SKU.ToString() != "" select sale.SKU),

It compiles but the column appears and is blank.

UPDATE: PROBLEM SOLVED

After some experimentation:

from sale in context.Sales
                    group sale by {sale.Order_ID, sale.SKU} into byOrder
                    select new
                    {
                        Order_ID = byOrder.Key.Order_ID
                        SKU = byOrder.Key.SKU
                        Charge = (from sale in byOrder where sale.Payment_Type == "Product charges                                   " select sale.Amount).Sum(),
                        Tax = (from sale in byOrder where sale.Payment_Detail == "Product Tax                                       " select sale.Amount).Sum(),
                        Fee = (from sale in byOrder where sale.Payment_Detail == "FBA Pick & Pack Fee                               " ||
                               sale.Payment_Detail == "Referral Fee on Item Price                        " select sale.Amount).Sum()
                        
                    };

                dataGridView1.DataSource = consolidated.ToList();

This can be achieved by using the GroupBy method from Linq. I prefer the query syntax for this case, so this is how it would look like:

var consolidated = 
  from sale in context.Sales
  group sale by sale.Order_ID into byOrder
  select new {
    Order_ID = byOrder.Key,
    Charge = (from sale in byOrder where sale.Detail == "Charge" select sale.Amount).Sum(),
    Tax = (from sale in byOrder where sale.Type == "Tax" select sale.Amount).Sum(),
    Fee = (from sale in byOrder where sale.Detail == "Fee" select sale.Amount).Sum(),
  };

dataGridView1.DataSource = consolidated.ToList();

If you need the serial ID column in the grid, you coud do this instead:

dataGridView1.DataSource = consolidated.Select(
  (sale, id) => new { ID = id, sale.Order_ID, sale.Charge, sale.Tax, sale.Fee }
).ToList();

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