代码之家  ›  专栏  ›  技术社区  ›  Bad Dub

使用LINQ到实体的时间跨度总和

  •  3
  • Bad Dub  · 技术社区  · 8 年前

    我有一个LINQ呼叫组,然后求和占有时间。将值勾选为新的时间跨度。这在以前工作得很好,但现在我需要将集合保留为IQueryable,而不是列表。

    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 回复  |  直到 8 年前
        1
  •  2
  •   Alexander Derck    8 年前

    我认为使用Linq到SQL/EF直接使用Linq不能很容易做到这一点,因为 PossionTime.Ticks . C#DateTime操作在转换为sql操作时非常有限。

    如果您的唯一要求是支持分页,那么您可以通过执行 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))
       });
    

    或者,您可以更改 武器项目 要存储的类 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)
        });
    
        2
  •  1
  •   NetMage    8 年前

    您可以创建 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秒,如果不是,则需要将总和转换为小时、分钟和秒。

    推荐文章