c# – 使用DBFunction或替代方法的EntityFramework GroupBy
我有100行不同日期的数据.我希望将结果按每30分钟相同的日期进行分组.
代替: 需要: 结果1,2016-02-02 13:33:24 原始查询: return await loc.Where(p => p.ReadTime >= df && p.ReadTime <= dt) .OrderBy(p => p.ReadTime) .ProjectTo<LocationModel>().ToListAsync(); 我尝试了什么: return await loc.Where(p => p.ReadTime >= df && p.ReadTime <= dt) .GroupBy(p => DbFunctions.TruncateTime(p.ReadTime)) .Select(p => new LocationModel { Lng = p.FirstOrDefault().Lng,Lat = p.FirstOrDefault().Lat }) .ToListAsync(); 堆栈跟踪错误:
解决方法
除了将所有数据加载到内存中并根据需要手动格式化之外,我可以想到用单个查询执行此操作的唯一可行方法是将行放入预定义日期“桶”并选择一行从每个桶.
桶的最合乎逻辑的选择是在您寻找30分钟间隔后的小时和半小时,例如: Result 1,2016-02-02 13:00:24,2016-02-02 13:00:00 (bucket 1) Result 1,2016-02-02 13:01:24,2016-02-02 13:02:24,2016-02-02 13:33:24,2016-02-02 13:30:00 (bucket 2) 要解决的下一个问题是选择每个桶使用哪一行.您可以使用的一种方法是确定最接近桶的日期(最小值)并使用它: from l in loc join bucket in ( from l in loc group l by new DateTime(l.ReadTime.Year,l.ReadTime.Month,l.ReadTime.Day,l.ReadTime.Hour,l.ReadTime.Minute < 30 ? 0 : 30,0) into g select g.Min(m => m.ReadTime) ) on l.ReadTime equals bucket select new LocationModel { Lng = l.FirstOrDefault().Lng,Lat = l.FirstOrDefault().Lat } 需要注意这种方法,但如果存在具有相同日期/时间值的行,则最终可能会出现重复.如果实体/表使用标识列作为其主键,并且以日期/时间顺序方式将行插入到表中,则可以使用该键来确定每个存储桶的行,因为该键实际上是按升序日期顺序排列的: from l in loc join bucket in ( from l in loc group l by new DateTime(l.ReadTime.Year,0) into g select g.Min(m => m.Id) ) on l.Id equals bucket select new LocationModel { Lng = l.FirstOrDefault().Lng,Lat = l.FirstOrDefault().Lat } 这将确保没有重复.否则,您需要在代码中过滤重复项或进一步扩展查询.我对你的特定领域了解不多,所以我会留下这部分给你解决. 我还应该指出Linq to SQL支持上述查询,但是如果不支持某些内容(例如DbFunctions.CreateDateTime),则可能需要将DbFunctions类用于带有EF的DateTime位. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |