Reputation: 637
I'm trying to build a new web app in VS2015 using the RC of the new asp.net and Entity Framework 7.
One thing I would like to be able to display is a "total of timespan" columns.
I'm trying to find a way of being able to retrieve the total duration across all video data that has been uploaded (I'm using NReco and FFProbe to get the media info from the file, which is where I get the duration from to upload to the DB)
When I'm uploading video data to a database, one of the properties in my Video model is a TimeSpan object.
I've been trawling the net and SO for a while, some of the suggested solutions I have tried haven't worked (more details below)
For context, here is my model
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; }
}
and my controller
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
...
}
var minutesOfVideo = new TimeSpan(_context.Videos.Sum(v => v.VideoDuration.Ticks));
but throws an
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.
I've also tried to do this
var minutesOfVideo = _context.Videos.Aggregate(TimeSpan.Zero, (sumSoFar, nextMyObject) => sumSoFar + nextMyObject.VideoDuration);
but this throws an
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
Is this even possible or do I need to look at writing either some Linq->Sql or some native SQL
I appreciate any answers of if this is doable
EDIT
Based on @Ricky's suggestion (thanks by the way)
If I try
var minutesOfVideo = _context.Videos.Select(v => v.VideoDuration).ToArray();
I get An exception of type 'System.InvalidCastException' occurred in EntityFramework.Core.dll but was not handled in user code, trying
var minutesOfVideo = _context.Videos.Select(v => v.VideoDuration).ToArray().Sum();
I get compiler errors
'TimeSpan[]' does not contain a definition for 'Sum' and the best extension method overload 'AsyncEnumerable.Sum(IAsyncEnumerable)' requires a receiver of type 'IAsyncEnumerable'
I'm starting to wonder if its worth me removing the timespan property from my video model and replacing it with two int's for hours and minutes...
Upvotes: 1
Views: 1339
Reputation: 10751
Usually the EF 7 will try to convert your LINQ expressions into SQL statement. Although it has limited capabilities that combine the database query and class properties accessing.
I suggest you may query all VideoDuration
from database, ToArray
then invoke Sum over the Array:
_context.Videos.Select(v => v.VideoDuration)
.ToArray()
.Select(vd => vd.TotalMinutes)
.Sum() // the return value is of type double
Upvotes: 1
Reputation: 637
So, I ended up taking the approach of editing my Video model with two new properties
public int VideoMinutes { get; set; }
public int VideoSeconds { get; set; }
then from NReco.GetMediaInfo I get my TimeSpan object, from that I populate my two new fields as properties from the constructed TimeStamp object.
That then allows me to do the following in my 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);
It may not be the cleanest solution but this is providing me what I need currently.
Upvotes: 0