Linq Left Join

      最近在开发一个内部的Report网站,外挂在POS系统上,因国内的POS系统基本都是无法自定义开发报表,源码已加密,无法客制化页面。而且厂商也不可能单独为你开发报表,每个公司都有自己的管理思维,所需的报表也不一样,当然除非公司的Money够多也愿意在IT投入,可以跟厂商谈谈定制化开发。

     这几年基本都在折腾SAP,把ASP.Net忘得也差不多,重新捡起来,因报表数据复杂,需要将两个存储过程的结果合并为一个报表,然后按门店汇总,再按城市汇总,并且结果在GridViw中镶套三层显示。比较好的办法就是用Linq对结果进行处理,而这两个结果集数据不太一样,需要用Linq Left,结果按goole到的案例去Coding,报表抛出异常:未将对象引用设置到对象的实例,左看右看折腾了一晚上没找到原因,早上再来看代码找到原因了,在Left Join时,右边的结果集,可能出现空的结果,字段赋值时需对表进行null的判断,代码如下:

通过存储过程从DB中得到两个DataTable,dtHy和dtYz,使用Linq先对这两个表按城市、门店、店员汇总

//Linq按店员汇总dtHy
var SumHYByDY = from hy in dtHy.AsEnumerable()
      group hy by new { city = hy.Field<string>("city"), mdmc = hy.Field<string>("mdmc"), dymc = hy.Field<string>("dymc") } into tb
      select new
      {
          city = tb.Key.city,
          mdmc = tb.Key.mdmc,
          dymc = tb.Key.dymc,
          hy_hys = tb.Sum(hy => Convert.ToInt32(hy["hys"] == DBNull.Value ? 0 : hy["hys"])),
          hy_hys_hb = tb.Average(hy => Convert.ToDecimal(hy["hys_hb"] == DBNull.Value ? 0 : hy["hys_hb"]))
      };
//Linq按店员汇总dtYz
var SumYZByDY = from yz in dtYz.AsEnumerable()
      group yz by new { city = yz.Field<string>("city"), mdmc = yz.Field<string>("mdmc"), dymc = yz.Field<string>("dymc") } into tb
      select new
      {
          city = tb.Key.city,
          mdmc = tb.Key.mdmc,
          dymc = tb.Key.dymc,
          yz_hys = tb.Sum(yz => Convert.ToInt32(yz["hys"] == DBNull.Value ? 0 : yz["hys"])),
          yz_hys_hb = tb.Average(yz => Convert.ToDecimal(yz["hys_hb"] == DBNull.Value ? 0 : yz["hys_hb"]))
      };

注意Group by多个字段时,请使用new { }.


第二步,对Linq结果集再次Linq Left Join:

//Linq按城市、门店、店员合并数据 LeftJoin
var JoinByDymc = from hy in SumHyByDYMC
     join yz in SumYzByDYMC 
     on new     { city = hy.city, mdmc = hy.mdmc, dymc = hy.dymc }
     equals new { city = yz.city, mdmc = yz.mdmc, dymc = yz.dymc }
     into LeftJoinTB
     from tb in LeftJoinTB.DefaultIfEmpty()
     select new
     {
         hy.city,
         hy.mdmc,
         hy.dymc,
         hy.hy_hys,
         hy.hy_hys_hb,
         yz_hys = tb == null ? 0 : tb.yz_hys,
         yz_hys_hb = tb == null ? 0 : tb.yz_hys_hb
     };

 左连接时,需把左边的Table放在Join的左边,同时把结果into 到一个临时的结果集中,并且对该结果集使用方法DefaultIfEmpty(),即:
into LeftJoinTB from tb in LeftJoinTB.DefaultIfEmpty()
问题来了,如果将 yz_hys = tb == null ? 0 : tb.yz_hys 修改为yz_hys = tb.yz_hys,那么将抛出异常:未将对象引用设置到对象的实例(NullReferenceException),所以必须对结果进行NUL的判断,这就是关键点


第三步,按门店汇总数据

//Linq按城市、门店汇总数据
var SumHyBymdmc = from dt in JoinByDymc
      group dt by new { city = dt.city , mdmc = dt.mdmc  }into tb 
      select new
      {
          city = tb.Key.city,
          mdmc = tb.Key.mdmc,
          hy_hys = tb.Sum(dt => dt.hy_hys),
          hy_hys_hb = tb.Average(dt => dt.hy_hys_hb),
          yz_hys = tb.Sum(dt => dt.yz_hys),
          yz_hys_hb = tb.Average(dt => dt.yz_hys_hb)
      };

第四步,按城市汇总数据

代码参照按门店汇总数据.

N久没有写C#的代码,最快速的方法就是Google,不过网上也没现成的列子,都是东拼西凑,然后按自己的逻辑自己改进调整,发现Linq确实是很强大,很方便做数据处理。搞笑的是这些天在C#,ABAP,SQL,Javascript,VBA之间切换,语法常常搞混了大笑

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值