如何使用linq添加子总行和总行

时间:2016-03-16 10:46:02

标签: c# entity-framework linq

我想为每个 BusinessTypeCode 添加子总计行,并为所有 BusinessTypeCode 添加总计。如何在我的linq中添加这两行并将每个businesstypecode放在下面。

我的当前代码

var query = (from _transaction in _entities.Transactions
             join _cd in _entities.Organisations on _transaction.Refno equals _cd.Refno
             join _b in _entities.BusinessType on _transaction.BusinessTypeCode equals _b.BusinessTypeCode
             group new
             {
                 _trans = _transaction,
                 cd = _cd,
             }
             by new { _transaction.BusinessTypeCode,_transaction.Refno, _cd.BusinessName, _b.Description } into _group
             orderby _group.Key.BusinessTypeCode
             select new
             {
                 BusinessTypeCode = _group.Key.BusinessTypeCode,
                 BusType = _group.Key.BusinessTypeCode + " - " +_group.Key.Description,
                 BusName = _group.Key.BusinessName,
                 BusL = _group.Sum(x=>x._trans.BusL),
                 BusInterrest = _group.Sum(x => x._trans.BusInterrest),
                 BusAdmin = _group.Sum(x => x._trans.BusAdmin),
                 BusPenalty = _group.Sum(x => x._trans.BusPenalty),
                 TotalBusCollected =_group.Sum(x=>x._trans.TotalBusCollected)
             });
DataTable dt=new DataTable();
DataSet ds = new DataSet();
ds.Tables.Add(query.CopyToDataTable());
ds.Tables[0].TableName = "Table1";
var subtotal = query.GroupBy(x=>x.BusinessTypeCode ).Select(s=>new
{
    BusinessTypeCode =s.Key,
    BusLSub = s.Sum(x=>x.BusL),
    BusInterrestSub = s.Sum(x=>x.BusInterrest),
    BusAdminSub = s.Sum(x=>x.BusAdmin),
    BusPenaltySub = s.Sum(x=>x.BusPenalty),
    TotalBusCollectedSub = s.Sum(x=>x.TotalBusCollected),
});
foreach (var a in subtotal)
{
    dt = ds.Tables[0];
    dt.NewRow();
    dt.Rows.Add(a.BusLSub, a.BusInterrestSub, a.BusAdminSub, a.BusPenaltySub, a.TotalBusCollectedSub );
}
return ds;

当前输出

BusType        |BusName   | BusL  |BusInterest|BusAdmin| BusPenalty|TotalBusCollected
1 - ACCOUNTING |HIGHVELD  |-23.91 | 0         |-22.84  | 0         |-46.75
1 - ACCOUNTING |BHP       |-50.81 |-79.21     |-76     |-20.02     |-226.04
2 - FOOD       |SAB       |-14.18 |-435.97    |-2.57   |-67.55     |-520.27
2 - FOOD       |DISTIL    |-43.05 |0          |-66,59  |0          |-109.64
3 - MINING     |ANGLOGOLD |-4.43  |0          |-72     |0          |-76.43
   -74.72      |-79.21    |-98.84 |-20.02     |-272.79
   -57.23      |-435.97   |-69.16 |-67.55     |-629.91
   -4.43       |0         |-72    |0          |-76.43

如何将其推送到BusinessTypeCode = BusinessTypeCode?的位置

输出支持

   BusType     |BusName   | BusL  |BusInterest|BusAdmin| BusPenalty|TotalBusCollected
1 - ACCOUNTING |HIGHVELD  |-23.91 | 0         |-22.84  | 0         |-46.75
1 - ACCOUNTING |BHP       |-50.81 |-79.21     |-76     |-20.02     |-226.04
--------------------------+-------+-----------+--------+-----------+-----------------
Sub Total                 |-74.72 |-79.21     |-98.84  |-20.02     |-272.79
--------------------------+-------+-----------+--------+-----------+-----------------
 2 - FOOD      |SAB       |-14.18 |-435.97    |-2.57   |-67.55     |-520.27
 2 - FOOD      |DISTIL    |-43.05 |0          |-66,59  |0          |-109.64
--------------------------+-------+-----------+--------+-----------+-----------------
Sub Total                 |-57.23 |-435.97    |-69.16  |-67.55     |-629.91
--------------------------+-------+-----------+--------+-----------+-----------------
3 - MINING     |ANGLOGOLD |-4.43  |0          |-72     |0          |-76.43
--------------------------+-------+-----------+--------+-----------+-----------------
Sub Total                 |-4.43  |0          |-72     |0          |-76.43
--------------------------+-------+-----------+--------+-----------+-----------------
GRAND TOTAL               |-136.38|-515.38    |-240    |-87.57     |-979.13

2 个答案:

答案 0 :(得分:0)

看起来你需要的是某种交错。我还没有对此进行测试,但您想要的想法类似于以下内容(假设您有一个名为BusRow的类而不是您的匿名类型)。我也冒昧地使子行的类型与BusRow相同,但是当你这样做时不一定是这种情况。

public static IEnumerable<BusRow> Interleave(List<BusRow> rowItems, List<BusRow> subTotalItems)
{
   for(int i = 0 ; i < rowItems.Count; ++i)
   {
     yield return rowItems[i];
     if(i > 0 && rowItems[i].BusinessTypeCode != rowItems[i-1].BusinessTypeCode)
     {
       yield return subTotalItems.Single(x => x.BusinessTypeCode == rowItems[i-1].BusinessTypeCode);
     }
   }
   yield return subTotalItems.Single(x => x.BusinessTypeCode == rowItems[rowItems.Count-1].BusinessTypeCode);
}

当然,您将更改原始查询以返回BusRow,如:

var subtotal = query.GroupBy(x=>x.BusinessTypeCode ).Select(s=>new BusRow
{
    BusinessTypeCode =s.Key,
    BusL = s.Sum(x=>x.BusL),
    BusInterrest = s.Sum(x=>x.BusInterrest),
    BusAdmin = s.Sum(x=>x.BusAdmin),
    BusPenalty = s.Sum(x=>x.BusPenalty),
    TotalBusCollected = s.Sum(x=>x.TotalBusCollected),
});

然后致电

var interleaved = Interleave(query, subtotal);
foreach (var a in interleaved)
{
    dt = ds.Tables[0];
    dt.NewRow();
    if(String.isNullOrEmpty(a.BusName)//format your subtotal row as you like - add --rows before and after
       dt.Rows.Add(a.BusL, a.BusInterrest, a.BusAdmin, a.BusPenalty, a.TotalBusCollected ); 
   else
     dt.Rows.Add(a.BusinessTypeCode, a.BusName, a.BusL, a.BusInterrest, a.BusAdmin, a.BusPenalty, a.TotalBusCollected ); //normal row
}

答案 1 :(得分:0)

由于我目前正在使用移动设备,因此无法验证此段代码。

您可以这样做:

foreach(var item in subtotal)
{
   var lastRecord = ds.Tables[0].Rows.LastOrDefault(r=>r["BusType"]==item.BusTypeCode);
   var lastIndex = ds.Tables[0].Rows.IndexOf(lastRecord);
   DataRow dr = ds.Tables[0].NewRow();
   dr["BusType"] = item.BusTypeCode;
   // etc.
   ds.Tables[0].Rows.InserAt(dr, lastIndex);
}

// insert the grand total row at the end

return ds;

这只是为了展示如何将当前DataSet输出转换为所需输出的想法。