linq 对Sum()函数的支持

首先看一段SQL语句:

SELECT
SUM(TASKAPPR) AS APPRCOUNT,
SUM(TASKLOCKED) AS LOCKEDCOUNT,
SUM(TASKCHECKED) AS CHECKEDCOUNT 
FROM (
SELECT 
(CASE WHEN ISAPPR =1 THEN 1 ELSE 0 END)  AS TASKAPPR,
(CASE WHEN ISLOCKED =1 THEN 1 ELSE 0 END)  AS TASKLOCKED,
(CASE WHEN ISCHECKED =1 THEN 1 ELSE 0 END)  AS TASKCHECKED
 FROM TASK)
 AS TEMP

 上面是对一个叫Task表的三个bit类型的字段进行数据统计,用到了三个case when 来排除空值,然后放到一个临时表里面再进行sum查询。 当然这只是简单的一些,估计在工作中会遇到到多个表连接,多个条件过滤再进行相关字段统计,那么估计代码下来,差不多也得个四五十行,如果你用的数据驱动是Ef,那么这个时候我估计你会先下意识的思考一下用Linq 或者Lamda表达式如何写,毕竟我想你前端的条件都已经封装给了Expression<Func<T,bool>>,你一定不想让你的程序中再出现红色的sql过滤条件。但是回过头来你又马上意识到用linq实现这样的业务场景也没那么容易,尤其是需要很多的判断和很多的sum(),更加坑爹的是按照以上sql的执行逻辑去写相应的linq语句的时候,你会很快发现进入到了死胡同。

Tasks.Select
(t=>new{
TASKAPPR=t.IsAppr==true?1:0,
TASKLOCKED=t.IsLocked==true?1:0,
TASKCHECKED=t.IsChecked==true?1:0,
})

  写到了上面你已经完全不知道该如何执行三个Sum函数,搜了半天攻略,发现面临多个Sum的时候都是进行分组group by (),而咱们这里完全不需要group By。到此,陷入死胡同,眼看快要下班,就开始用自己炉火纯青的技术编写了一个sql 存储过程。然后交工完成。

     但是这件事情一直就在我心中留下了一些遗憾,虽然说存储过程的执行效率要比Linq to Entity  快点,但是sql语句属于执行语句,不分大小写,后期维护特别艰难,而linq却属于强类型代码,更容易维护拓展,再加上net4.5已经对Linq的性能做了一些优化,用linq还是ADO.NET执行之间的性能对比已经显得意义不大。终于有一天,看到国外的某一程序员解决了这一问题,代码如下:

  from task in Tasks
                           // where express
                           group task by 1 into g
                           select new  {
                                 TASKAPPR=g.Sum(t.IsAppr==true?1:0),
                                 TASKLOCKED=g.Sum(t.IsLocked==true?1:0),
                                 TASKCHECKED=g.Sum(t.IsChecked==true?1:0)
                           }

   这里巧妙的利用了group by 语句。不再是group by 某一个或者多个字段进行分组。达成的效果与上面的sql语句一致。

   上面代码利用的事LinPad,所以不必纠结写法上的差异。

原文地址:https://www.cnblogs.com/lpfsky/p/3629785.html