首页 > 代码库 > [.NET] EF LINQ 按时间对数据分类汇总
[.NET] EF LINQ 按时间对数据分类汇总
========================================================
作者:qiujuer
博客:blog.csdn.net/qiujuer
网站:www.qiujuer.net
开源库:Genius-Android
转载请注明出处:http://blog.csdn.net/qiujuer/article/details/41868331
========================================================
发现国内弄 Mvc 和 WebAPI 的人简直少的可怜啊;前段时间发了大量的 WebAPI 的相关博文看的人不多;可以说是无人问津。
在对数据的操作中,对一堆数据的分类汇总是比较常见的,特别是按照时间进行分类汇总。比如算出某一天,某一月的数据总量等等。而鉴于国内研究的人少所以遇到一些问题简直没法查询,其中就包括:
<ExceptionMessage> LINQ to Entities 不识别方法“System.String ToString(System.String)”,因此该方法无法转换为存储表达式。 </ExceptionMessage>
现在我有一堆存储在数据库中的数据;其数据简单格式如下:
public class DataModel { public int Id { get; set; } public string Data { get; set; } public DateTime Time { get; set; } }就只有一个数据,一个时间,一个标志字段。
现在这样的数据有一大堆,各个时间段的都有;我想要统计分别每天有哪些数据存在。
方案一
最傻,最直接;第一种方法你首先查询该数据库中所有数据;然后使用for 或者foreach 循环遍历整个数据,然后判断加入到不同的 List 列表中,然后打包返回。
该方法未使用 LINQ,而是使用的简单的操作来实现;这里就不贴出代码了。
方案二
思路清晰。在这中方法中在进行SQL 查询时就把返回的时间 改成 “天” ,而没有时间的格式;然后再进行分类汇总,最后返回想要的字段。
var note2 = db.Notes // 先进行了时间字段变更为String字段,切只保留到天 .Select(n => new { Data = http://www.mamicode.com/n.Data, Time = n.Time.ToString("yyyy-MM-dd") })>方法似乎很正确,但是运行后:<Error> <Message>出现错误。</Message> <ExceptionMessage> LINQ to Entities 不识别方法“System.String ToString(System.String)”,因此该方法无法转换为存储表达式。 </ExceptionMessage> <ExceptionType>System.NotSupportedException</ExceptionType> <StackTrace>...</StackTrace> </Error>这时就出现了这样的情况,是我们的思路错了?不是,思路完全正确。只是在 EF 中的 LINQ 不能识别 ToString 而已。
方案三
思路不变,任然才有方案二的思路,以及大部分代码,只更改一小部分。
var note3 = db.Notes
// 先进行了时间字段变更为String字段,切只保留到天
// 采用拼接的方式
.Select(n => new { Data = http://www.mamicode.com/n.Data, Time = n.Time.Year + "-" + n.Time.Month + "-" + n.Time.Day })>既然不能返回,那我们就来自己拼接;这种方式能够正确执行并返回正确数据。推荐!!!
方案四
换个思路,既然EF LINQ中无法使用 ToString ,那么单独的 LINQ 呢?
// 先进行数据查询,返回数据
var datas = await db.Notes.ToListAsync();
// 然后在内存中使用 LINQ
var note4 = datas.Select(n => new { Data = http://www.mamicode.com/n.Data, Time = n.Time.ToString("yyyy-MM-dd") })>至于分类汇总的思路不变;只是把ToString 放到了独立的LINQ 中使用而已;实践证明,这个是可行的方案。同样推荐!!!
区别是啥?
第二种思路无法成功,主要是 EF 识别不了 ToString 中的操作,这个很好理解,因为EF 最终是需要换成SQL 语句进行执行的。如果我们加上了 ToString 看似可以,但是其实完全不合理,因为电脑不知道我们 ToString 中究竟有些啥,所以它不知道应该转换为什么样的 SQL 语句。
所以我们在 方案三中直接告诉了他,就是使用时间字段的对应参数进行组装,所以他能正确执行。
至于 方案四 这个就更加好说了,因为ToString 是放在查询后,所以它无需进行对应的SQL 语句的操作了,所以这个时候随你怎么弄都不为过。
方案三与方案四 结果完全一样,代码也几乎一样;但是其执行上却相差甚远!
为何?
- 因为 方案三 基本上是把所有的工作放在了 SQL 上执行,这边只负责接收成果就OK 了!
- 而 方案四 则是获取数据是在 SQL 操作,但是数据的处理是放在服务器端内存中进行的!
其优劣性
- 如果你的 SQL 数据性能远远大于 你的服务器后台 配置,那么才有第三方案 是比较划算的。
- 如果你的 服务器的内存不错,分析也不错;能完全胜任其数据处理的话 第四方案 是你的不二选择。
这个其处理的时间就不太好估计了,毕竟每个人的电脑都不尽相同;所以看个人估计吧!一般情况下两种都差距不大。至于没有说第一种,因为第一种的性能上有待考虑;当然如果你的分析算法够OK 的话,那就可以与 第四方案 拼个你死我活。
实际使用
<ArrayOfNoteInfo xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/GeniusSpace.Controllers.Api"> <NoteInfo> <Changes> <SNote> <Content>似的撒旦</Content> <Time>2014-12-11</Time> </SNote> <SNote> <Content>sewrwfqf</Content> <Time>2014-12-11</Time> </SNote> <SNote> <Content>sgewhsdwqd</Content> <Time>2014-12-11</Time> </SNote> </Changes> <Time>2014-12-11</Time> </NoteInfo> <NoteInfo> <Changes> <SNote> <Content>asgafasgre</Content> <Time>2014-12-10</Time> </SNote> <SNote> <Content>dgwetwet</Content> <Time>2014-12-10</Time> </SNote> </Changes> <Time>2014-12-10</Time> </NoteInfo> <NoteInfo> <Changes> <SNote> <Content>rwqyhtrjhdf</Content> <Time>2014-12-09</Time> </SNote> </Changes> <Time>2014-12-09</Time> </NoteInfo> </ArrayOfNoteInfo>这是我这边使用的情况,当然其参数与上面的参数不对;但是其分类汇总是完成了的。
采用的是 第三方案 ,其SQL 语句如下:
SELECT [Project2].[C2] AS [C1], [Project2].[C1] AS [C2], [Project2].[C4] AS [C3], [Project2].[Content] AS [Content], [Project2].[C3] AS [C4] FROM ( SELECT [Distinct1].[C1] AS [C1], 1 AS [C2], [Extent2].[Content] AS [Content], CASE WHEN ([Extent2].[Content] IS NULL) THEN CAST(NULL AS varchar(1)) ELSE CASE WHEN (DATEPART (year, [Extent2].[Published]) IS NULL) THEN N'' ELSE CAST( DATEPART (year, [Extent2].[Published]) AS nvarchar(max)) END + N'-' + CASE WHEN (DATEPART (month, [Extent2].[Published]) IS NULL) THEN N'' ELSE CAST( DATEPART (month, [Extent2].[Published]) AS nvarchar(max)) END + N'-' + CASE WHEN (DATEPART (day, [Extent2].[Published]) IS NULL) THEN N'' ELSE CAST( DATEPART (day, [Extent2].[Published]) AS nvarchar(max)) END END AS [C3], CASE WHEN ([Extent2].[Content] IS NULL) THEN CAST(NULL AS int) ELSE 1 END AS [C4] FROM (SELECT DISTINCT CASE WHEN (DATEPART (year, [Extent1].[Published]) IS NULL) THEN N'' ELSE CAST( DATEPART (year, [Extent1].[Published]) AS nvarchar(max)) END + N'-' + CASE WHEN (DATEPART (month, [Extent1].[Published]) IS NULL) THEN N'' ELSE CAST( DATEPART (month, [Extent1].[Published]) AS nvarchar(max)) END + N'-' + CASE WHEN (DATEPART (day, [Extent1].[Published]) IS NULL) THEN N'' ELSE CAST( DATEPART (day, [Extent1].[Published]) AS nvarchar(max)) END AS [C1] FROM [dbo].[Notes] AS [Extent1] ) AS [Distinct1] LEFT OUTER JOIN [dbo].[Notes] AS [Extent2] ON ([Distinct1].[C1] = (CASE WHEN (DATEPART (year, [Extent2].[Published]) IS NULL) THEN N'' ELSE CAST( DATEPART (year, [Extent2].[Published]) AS nvarchar(max)) END + N'-' + CASE WHEN (DATEPART (month, [Extent2].[Published]) IS NULL) THEN N'' ELSE CAST( DATEPART (month, [Extent2].[Published]) AS nvarchar(max)) END + N'-' + CASE WHEN (DATEPART (day, [Extent2].[Published]) IS NULL) THEN N'' ELSE CAST( DATEPART (day, [Extent2].[Published]) AS nvarchar(max)) END)) OR (([Distinct1].[C1] IS NULL) AND (CASE WHEN (DATEPART (year, [Extent2].[Published]) IS NULL) THEN N'' ELSE CAST( DATEPART (year, [Extent2].[Published]) AS nvarchar(max)) END + N'-' + CASE WHEN (DATEPART (month, [Extent2].[Published]) IS NULL) THEN N'' ELSE CAST( DATEPART (month, [Extent2].[Published]) AS nvarchar(max)) END + N'-' + CASE WHEN (DATEPART (day, [Extent2].[Published]) IS NULL) THEN N'' ELSE CAST( DATEPART (day, [Extent2].[Published]) AS nvarchar(max)) END IS NULL)) ) AS [Project2] ORDER BY [Project2].[C1] ASC, [Project2].[C4] ASC从语句可以看出,其分类汇总,以及查询全部都是在SQL端完成。
按天分类实现了,按月、按年、按小时那还用说么?
如果你有更好的思路,还希望能写在下面一起交流交流。
========================================================作者:qiujuer
博客:blog.csdn.net/qiujuer
网站:www.qiujuer.net
开源库:Genius-Android
转载请注明出处:http://blog.csdn.net/qiujuer/article/details/41868331
========================================================
[.NET] EF LINQ 按时间对数据分类汇总
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。