整体框架7 / LINQ - 获取时间跨度对象的总和

时间:2016-03-15 22:56:02

标签: c# entity-framework sum timespan entity-framework-core

我正在尝试使用新的asp.net和Entity Framework 7的RC在VS2015中构建一个新的Web应用程序。

我希望能够显示的一个词是“总时间跨度”列。

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

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

我一直在拖网和SO一段时间,我试过的一些建议的解决方案没有用(下面有更多详情)

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

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)); 

但抛出

  

EntityFramework.Core.dll中出现'System.InvalidCastException'类型的异常,但未在用户代码中处理

     

其他信息:指定的演员表无效。

我也尝试过这样做

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

但这会引发

  

EntityFramework.Core.dll中出现“System.NotImplementedException”类型的异常,但未在用户代码中处理

     

其他信息:Remotion.Linq.Clauses.ResultOperators.AggregateFromSeedResultOperator

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

我感谢任何答案,如果这是可行的

修改

基于@Ricky的建议(感谢顺便说一下)

如果我尝试

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

我得到 EntityFramework.Core.dll中出现“System.InvalidCastException”类型的异常但未在用户代码中处理,尝试

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

我收到编译错误

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

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

2 个答案:

答案 0 :(得分:1)

通常,EF 7会尝试将您的LINQ表达式转换为SQL语句。虽然它具有有限的功能,可以组合数据库查询和类属性访问。

我建议你可以从数据库VideoDuration查询所有ToArray,然后在数组上调用Sum:

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

答案 1 :(得分:0)

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

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);

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