I'm working on a Asp.Net Core project right now. I have an entity named Course
and an entity named Episode
. they have one-to-many relation so that each Course
has many Episods
inside itself.
This is my Episode.cs:
public class Episode
{
[Key]
public int EpisodeId { get; set; }
[Required]
public int CourseId { get; set; }
[Display(Name = "عنوان اپیزود")]
[Required(ErrorMessage ="لطفا {0} را وارد کنید")]
[MaxLength(ErrorMessage ="{0} نمیتواند بیش تر از {1}کاراکتر باشد")]
public string EpisodeTitle { get; set; }
public string EpisodeFileName { get; set; }
[Display(Name = "مدت زمان اپیزود")]
[Required(ErrorMessage = "لطفا {0} را وارد کنید")]
public TimeSpan? EpisodeTimeLength { get; set; }
[Display(Name = "رایگان")]
[Required(ErrorMessage = "لطفا {0} را وارد کنید")]
public bool IsFree { get; set; }
public DateTime CreateDate { get; set; } = DateTime.Now;
#region Navigation Properties
[ForeignKey("CourseId")]
public Course.Courses.Course Course { get; set; }
#endregion
}
My question is about this part: public TimeSpan? EpisodeTimeLength { get; set; }
.
I want to use the method OrderBy() to sort my courses so that which course has more total EpisodeTimeLength become at first.
For example, if the total EpisodeTimeLength of my first Course
be 12h, and the second one be 15h, the second one will be considerd at first.
I tried the below ways:
1- dbContext.Courses.OrderBy( c => new TimeSpan( c.Episodes.Sum(e=> e.EpisodeTimeLength.Ticks));
2- dbContext.Courses.OrderBy( c =>( c.Episodes.Sum(e=> e.EpisodeTimeLength));
But none of them worked and I got the error: cannot implicity convert type 'System.TimeSpan' to 'long'!
So anyone can tell me How I can handle it?
CodePudding user response:
Your TimeSpan variable is nullable, so you need to use Value in your expression and you do not need create TimeSpan object inside LINQ method. This code should work:
dbContext.Courses.OrderBy( c => c.Episodes.Sum(e=> e.EpisodeTimeLength.Value.Ticks));
CodePudding user response:
Since TimeSpan
already defines an operator
, you can use it. Try this:
.OrderBy(c => c.Episodes.Select(e => e.EpisodeTimeLength.Value)
.Aggregate(TimeSpan.Zero, (x, y) => x y))
This first projects all episodes onto the Value
of their lengths (assuming that you want a bad exception if an episode length has no value), then aggregates with the built in
operator.
If you do not want an exception, but want to use a zero length when no length is known, then this:
.OrderBy(c => c.Episodes.Select(e => e.EpisodeTimeLength ?? TimeSpan.Zero)
.Aggregate(TimeSpan.Zero, (x, y) => x y))
If you are absolutely sure there will always be at least one episode in each course c
, then you can omit the TimeSpan.Zero
from the Aggregate
call (the second line). So that would be
.OrderBy(c => c.Episodes.Select(e => e.EpisodeTimeLength.Value)
.Aggregate((x, y) => x y))
respectively
.OrderBy(c => c.Episodes.Select(e => e.EpisodeTimeLength ?? TimeSpan.Zero)
.Aggregate((x, y) => x y))