Entity Framework 7 / LINQ - 获取时间跨度对象的总和

Entiity Framework 7 / LINQ - Get sum of timespan objects

我正在尝试使用新 asp.net 和 Entity Framework 7.

的 RC 在 VS2015 中构建一个新的网络应用程序

我希望能够显示的一件事是 "total of timespan" 列。

我正在尝试找到一种能够检索已上传的所有视频数据的总持续时间的方法(我正在使用 NReco 和 FFProbe 从文件中获取媒体信息,这是我的位置获取上传到数据库的持续时间)

当我将视频数据上传到数据库时,我的 Video 模型中的属性之一是 TimeSpan 对象。

我已经在网上拖网了一段时间了,我尝试过的一些建议的解决方案没有奏效(下面有更多详细信息)

对于上下文,这是我的模型

public class Video
{
    public int Id { get; set; }
    public DateTime DateOfVideo { get; set; }
    public string Road { get; set; }
    public string RegistrationNumber { get; set; }
    public List<Keyword> Keywords { get; set; }
    public TimeSpan VideoDuration { get; set; }
    public string User { get; set; }
    public DateTime UploadDate { get; set; }
}

和我的控制器

public class HomeController : Controller
{
    private readonly UserManager<ApplicationUser> _userManager;
    private readonly IHostingEnvironment _environment;
    private readonly CcContext _context;

    public HomeController(UserManager<ApplicationUser> userManager, IHostingEnvironment environment, CcContext context)
    {
        _userManager = userManager;
        _environment = environment;
        _context = context;
    }
    ... 
    Various controller actions and methods removed for brevetiy 
    ...
}

到目前为止我已经尝试过的事情

based on this SO answer

 var minutesOfVideo = new TimeSpan(_context.Videos.Sum(v => v.VideoDuration.Ticks)); 

但抛出

An exception of type 'System.InvalidCastException' occurred in EntityFramework.Core.dll but was not handled in user code

Additional information: Specified cast is not valid.

我也试过这样做

var minutesOfVideo  = _context.Videos.Aggregate(TimeSpan.Zero, (sumSoFar, nextMyObject) => sumSoFar + nextMyObject.VideoDuration);

但这会抛出一个

An exception of type 'System.NotImplementedException' occurred in EntityFramework.Core.dll but was not handled in user code

Additional information: Remotion.Linq.Clauses.ResultOperators.AggregateFromSeedResultOperator

这是否可能,或者我是否需要考虑编写一些 Linq->Sql 或一些本机 SQL

我感谢任何可行的答案

编辑

根据@Ricky 的建议(顺便感谢)

如果我尝试

var minutesOfVideo = _context.Videos.Select(v => v.VideoDuration).ToArray();

我得到 类型 'System.InvalidCastException' 的异常发生在 EntityFramework.Core.dll 但未在用户代码中处理 ,正在尝试

var minutesOfVideo = _context.Videos.Select(v => v.VideoDuration).ToArray().Sum();

我收到编译器错误

'TimeSpan[]' 不包含 'Sum' 的定义,最佳扩展方法重载 'AsyncEnumerable.Sum(IAsyncEnumerable)' 需要类型为 'IAsyncEnumerable'[=65 的接收器=]

我开始怀疑我是否值得从我的视频模型中删除时间跨度 属性 并将其替换为两个 int 的小时和分钟...

通常 EF 7 会尝试将您的 LINQ 表达式转换为 SQL 语句。尽管它结合了数据库查询和 class 属性访问的功能有限。

我建议您可以从数据库中查询所有 VideoDurationToArray 然后对数组调用求和:

_context.Videos.Select(v => v.VideoDuration)
    .ToArray()
    .Select(vd => vd.TotalMinutes)
    .Sum() // the return value is of type double

所以,我最终采用了使用两个新属性编辑 Video 模型的方法

public int VideoMinutes { get; set; }
public int VideoSeconds { get; set; }

然后从 NReco.GetMediaInfo 我得到我的 TimeSpan 对象,从中我填充我的两个新字段作为构造的 TimeStamp 对象的属性。

这样我就可以在 HomeController 中执行以下操作

        var totalMinsOfVideo = _context.Videos.Select(v => v.VideoMinutes).Sum();
        var totalSecsOfVideo = _context.Videos.Select(v => v.VideoSeconds).Sum();
        var total = new TimeSpan(0, totalMinsOfVideo, totalSecsOfVideo);

它可能不是最干净的解决方案,但它提供了我目前需要的东西。