Entity Framework Core 中 TimeSpan 的总和

Posted

技术标签:

【中文标题】Entity Framework Core 中 TimeSpan 的总和【英文标题】:Sum of TimeSpan in Entity Framework Core 【发布时间】:2021-04-08 00:00:21 【问题描述】:

我有一个视图模型用于在索引页面上显示我的课程

public class ShowCourseListItemViewModel

    public int CourseId  get; set; 
    public string Title  get; set; 
    public string ImageName  get; set; 
    public int Price  get; set; 
    public TimeSpan TotalTime  get; set; 

我有一个获取所有课程的服务:

...
return result.Include(e => e.CourseEpisodes).Select(c => new ShowCourseListItemViewModel()

    CourseId = c.CourseId,
    Title = c.CourseTitle,
    ImageName = c.CourseImageName,
    Price = c.CoursePrice,
    TotalTime = new TimeSpan(c.CourseEpisodes.Sum(e => e.EpisodeTime.Ticks)) <== Error is Here
).Skip(skip).Take(take).ToList();
...

错误文本:

处理请求时发生未处理的异常。 InvalidOperationException:LINQ 表达式 'DbSet() .Where(c0 => EF.Property(EntityShaperExpression: EntityType:课程 ValueBufferExpression:ProjectionBindingExpression: EmptyProjectionMember IsNullable: False , "CourseId") != null && object.Equals(objA: (object)EF.Property(EntityShaperExpression: EntityType: 课程 ValueBufferExpression:ProjectionBindingExpression: EmptyProjectionMember IsNullable: False , "CourseId"), objB: (object)EF.Property(c0, "CourseId"))) .Sum(c0 => c0.EpisodeTime.Ticks)' 无法翻译。要么重写 以可翻译的形式查询,或切换到客户评估 通过插入对“AsEnumerable”、“AsAsyncEnumerable”的调用,显式地 “ToList”或“ToListAsync”。看 https://go.microsoft.com/fwlink/?linkid=2101038 了解更多信息。

我认为问题是TimeSpan 的总和。对这个总结有什么建议吗?

【问题讨论】:

尝试用c.CourseEpisodes.ToList().Sum替换c.CourseEpisodes.Sum 如果您将.AsEnumerable() 放在.Select( 之前,您会将查询数据拉到客户端,然后在客户端计算Select 结果 - 您可能希望将.Select(c =&gt; new c.CourseId, c.CourseTitle, c.CourseImageName, c.CoursePrice ) 放在Include 之前进行过滤数据拉到客户端。 【参考方案1】:
        return result.Include(e => e.CourseEpisodes).AsEnumerable()
            .Select(c => new ShowCourseListItemViewModel()
            
                CourseId = c.CourseId,
                Title = c.CourseTitle,
                ImageName = c.CourseImageName,
                Price = c.CoursePrice,
                TotalTime = new TimeSpan(c.CourseEpisodes.ToList().Sum(e => e.EpisodeTime.Ticks))
            ).Skip(skip).Take(take).ToList();

【讨论】:

请不要只发布代码作为答案,还要解释您的代码的作用以及它如何解决问题的问题。带有解释的答案通常更有帮助、质量更好,并且更有可能吸引投票。【参考方案2】:

在执行Select 之前,您需要通过调用诸如ToList 之类的方法来执行查询,因为EF 不知道如何将该部分转换为SQL。试试这个:

return result.Include(e => e.CourseEpisodes).Skip(skip).Take(take).ToList()
.Select(c => new ShowCourseListItemViewModel()

    CourseId = c.CourseId,
    Title = c.CourseTitle,
    ImageName = c.CourseImageName,
    Price = c.CoursePrice,
    TotalTime = new TimeSpan(c.CourseEpisodes.Sum(e => e.EpisodeTime.Ticks))
);

【讨论】:

以上是关于Entity Framework Core 中 TimeSpan 的总和的主要内容,如果未能解决你的问题,请参考以下文章

Entity Framework Core 数据保存原理详解

使用 ASP.NET Core 和 Entity Framework Core 进行集成测试 - 如何在每次测试时恢复数据库中的测试数据?

在 Entity Framework Core 中使用 [ComplexType]

在 Entity Framework Core 中使用 SQL 视图

Entity Framework Core 中 TimeSpan 的总和

Entity Framework优化一:引发了“System.Data.Entity.Core.EntityCommandExecutionException”类型的异常