【问题标题】:Entiity Framework 7 / LINQ - Get sum of timespan objectsEntity Framework 7 / LINQ - 获取时间跨度对象的总和
【发布时间】:2016-03-15 22:56:01
【问题描述】:

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

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

我正在尝试找到一种能够检索已上传的所有视频数据的总持续时间的方法(我正在使用 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)); 

但抛出一个

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”类型的接收器

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

【问题讨论】:

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


    【解决方案1】:

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

    我建议您可以从数据库中查询所有VideoDurationToArray 然后在数组上调用 Sum:

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

    【讨论】:

    • 谢谢,@Ricky,很遗憾,您的伪代码不起作用,请参阅我在原始帖子中的更新
    • Sql Server 中VideoDuration 的数据类型是什么?
    • 嗨@Ricky,数据类型是TimeVideoDuration(time(7), not null)
    • @Chris 现在我的代码可以实际运行了。 TimeSpan[] 不能Sum 所以你必须把它变成TotalMinutes 然后Sum
    【解决方案2】:

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

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

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

    【讨论】:

      猜你喜欢
      • 2016-05-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-10-05
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多