使用LINQ to Entities的Timespans总和

时间:2018-03-02 18:51:32

标签: c# .net linq linq-to-entities timespan

我有一个LINQ调用组,然后将PossessionTime.Tick值作为新的Timespan求和。这之前工作正常,但现在我需要将集合保持为IQueryable而不是List。

PossessionTime = new TimeSpan(x.Sum(p => p.PossessionTime.Ticks))

通过此更改,我现在收到以下错误:

  

LINQ中仅支持无参数构造函数和初始值设定项   实体。

我已经研究过使用DbFunctions,但它没有任何可以帮助我不思考的东西。

我唯一的选择是将列表移动到内存中并将时间相加吗?

IQueryable如下:

return stats.GroupBy(x => x.Id).OrderByDescending(x => x.Sum(a => a.Kills))
            .Select(x => new WeaponItem
            {         
                PossessionTime = new TimeSpan(x.Sum(p => p.PossessionTime.Ticks))
            });

我需要将它保持为IQueryable,因为我在分页中使用它。

2 个答案:

答案 0 :(得分:1)

我不认为你能够使用Linq-to-SQL / EF轻松地使用PossionTime.Ticks使用直接linq。转换为sql操作时,C#DateTime操作非常有限。

如果您的唯一要求是支持分页,您可以在分页操作后进行WeaponItem投影,并将页面拉入记忆中,从而轻松实现自己:

return stats
   .GroupBy(x => x.Id)
   .OrderByDescending(x => x.Sum(a => a.Kills))
   // paginatation
   .Skip(pageNumber * pageSize)
   .Take(pageSize)
   // pull paged result set into memory to make life easy
   .ToList()
   // transform into WeaponItem
   .Select(x => new WeaponItem
   {         
        PossessionTime = new TimeSpan(x.Sum(p => p.PossessionTime.Ticks))
   });

或者,您可以将WeaponItem类更改为存储PossesionTimeTicks,然后将PossesionTime作为计算属性提供。这可能会绕过限制:

public class WeaponItem
{
    public long PosseionTimeTicks {get;set;}
    public TimeSpan PossesionTime {get{ return new TimeSpan(PosseionTimeticks); }
}

然后我认为您应该能够将查询保持为IQueryable:

return stats
    .GroupBy(x => x.Id)
    .OrderByDescending(x => x.Sum(a => a.Kills))
    .Select(x => new WeaponItem
    {         
        PossessionTimeTicks = x.Sum(p => p.PossessionTime.Ticks)
    });

答案 1 :(得分:0)

您可以使用TimeSpan从HMS创建DBFunctions.CreateTime,这样您就可以进行数学转换:

return stats.GroupBy(x => x.Id).OrderByDescending(x => x.Sum(a => a.Kills))
            .Select(x => new WeaponItem
            {         
                PossessionTime = DBFunctions.CreateTime(0, 0, x.Sum(p => DBFunctions.DiffSeconds(p.PossessionTime, TimeSpan.Zero)))
            });

注意:我假设CreateTime接受秒参数> = 60秒,否则,您需要将总和转换为小时,分钟和秒。