如何在 C# 中的 Sum() 方法中获取 TimeSpan 属性的总数?
how to get total of TimeSpan properties inside a Sum() methode in c#?
我现在正在做一个 Asp.Net 核心项目。我有一个名为 Course
的实体和一个名为 Episode
的实体。它们具有一对多关系,因此每个 Course
内部都有许多 Episods
。
这是我的 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
}
我的问题是关于这部分的:public TimeSpan? EpisodeTimeLength { get; set; }
。
我想使用方法 OrderBy() 对我的课程进行排序,以便哪个课程的总 EpisodeTimeLength 排在第一位。
比如我第一个Course
的总EpisodeTimeLength是12h,第二个是15h,那么会先考虑第二个。
我尝试了以下方法:
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));
但是其中 none 起作用了,我得到了错误:无法将类型 'System.TimeSpan' 隐式转换为 'long'!
所以谁能告诉我我该如何处理?
您的 TimeSpan 变量可以为空,因此您需要在表达式中使用 Value 并且不需要在 LINQ 方法中创建 TimeSpan 对象。此代码应该有效:
dbContext.Courses.OrderBy( c => c.Episodes.Sum(e=> e.EpisodeTimeLength.Value.Ticks));
因为TimeSpan
已经定义了一个operator +
,你可以使用它。试试这个:
.OrderBy(c => c.Episodes.Select(e => e.EpisodeTimeLength.Value)
.Aggregate(TimeSpan.Zero, (x, y) => x + y))
这首先将所有剧集投影到其长度的 Value
上(假设如果剧集长度没有值,您想要一个错误的例外),然后使用内置的 +
运算符进行聚合。
如果您不希望出现异常,但希望在长度未知时使用零长度,那么:
.OrderBy(c => c.Episodes.Select(e => e.EpisodeTimeLength ?? TimeSpan.Zero)
.Aggregate(TimeSpan.Zero, (x, y) => x + y))
如果您完全确定每门课程总是至少有一集 c
,那么您可以省略 Aggregate
调用(第二行)中的 TimeSpan.Zero
.那就是
.OrderBy(c => c.Episodes.Select(e => e.EpisodeTimeLength.Value)
.Aggregate((x, y) => x + y))
分别
.OrderBy(c => c.Episodes.Select(e => e.EpisodeTimeLength ?? TimeSpan.Zero)
.Aggregate((x, y) => x + y))
最后,您可能需要这样的逻辑:如果至少有一集缺少长度,那么总数应该是未定义的 (null
)。在那种情况下,使用 Nullable<>
上自动存在的提升 +
。那将是:
.OrderBy(c => c.Episodes.Select(e => e.EpisodeTimeLength)
.Aggregate((TimeSpan?)TimeSpan.Zero, (x, y) => x + y))
或:
.OrderBy(c => c.Episodes.Select(e => e.EpisodeTimeLength)
.Aggregate((x, y) => x + y))
如果您知道 .Episodes
不为空,在这些情况下,您将在最短课程之前自行排序所有总长度为“未定义”的课程。
当然,.Select
并不是严格需要的,因为它们可以内置到 .Aggregate
使用的 lambda 中,例如:
.OrderBy(c => c.Episodes
.Aggregate((TimeSpan?)TimeSpan.Zero, (x, y) => x.EpisodeTimeLength + y.EpisodeTimeLength))
好吧,既然 .OrderBy
就是您所要求的,您不妨按照 fatherOfWine 的小小回答所建议的那样使用 .Ticks
。但是,我在您对他的回答的评论中看到您可能希望保留总课程长度。在这种情况下,您可以只说 .Select
而不是 .OrderBy
,例如:
var allCourseLengths = dbContext.Courses
.Select(c => c.Episodes.Select(e => e.EpisodeTimeLength.Value)
.Aggregate(TimeSpan.Zero, (x, y) => x + y));
等等。
我现在正在做一个 Asp.Net 核心项目。我有一个名为 Course
的实体和一个名为 Episode
的实体。它们具有一对多关系,因此每个 Course
内部都有许多 Episods
。
这是我的 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
}
我的问题是关于这部分的:public TimeSpan? EpisodeTimeLength { get; set; }
。
我想使用方法 OrderBy() 对我的课程进行排序,以便哪个课程的总 EpisodeTimeLength 排在第一位。
比如我第一个Course
的总EpisodeTimeLength是12h,第二个是15h,那么会先考虑第二个。
我尝试了以下方法:
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));
但是其中 none 起作用了,我得到了错误:无法将类型 'System.TimeSpan' 隐式转换为 'long'!
所以谁能告诉我我该如何处理?
您的 TimeSpan 变量可以为空,因此您需要在表达式中使用 Value 并且不需要在 LINQ 方法中创建 TimeSpan 对象。此代码应该有效:
dbContext.Courses.OrderBy( c => c.Episodes.Sum(e=> e.EpisodeTimeLength.Value.Ticks));
因为TimeSpan
已经定义了一个operator +
,你可以使用它。试试这个:
.OrderBy(c => c.Episodes.Select(e => e.EpisodeTimeLength.Value)
.Aggregate(TimeSpan.Zero, (x, y) => x + y))
这首先将所有剧集投影到其长度的 Value
上(假设如果剧集长度没有值,您想要一个错误的例外),然后使用内置的 +
运算符进行聚合。
如果您不希望出现异常,但希望在长度未知时使用零长度,那么:
.OrderBy(c => c.Episodes.Select(e => e.EpisodeTimeLength ?? TimeSpan.Zero)
.Aggregate(TimeSpan.Zero, (x, y) => x + y))
如果您完全确定每门课程总是至少有一集 c
,那么您可以省略 Aggregate
调用(第二行)中的 TimeSpan.Zero
.那就是
.OrderBy(c => c.Episodes.Select(e => e.EpisodeTimeLength.Value)
.Aggregate((x, y) => x + y))
分别
.OrderBy(c => c.Episodes.Select(e => e.EpisodeTimeLength ?? TimeSpan.Zero)
.Aggregate((x, y) => x + y))
最后,您可能需要这样的逻辑:如果至少有一集缺少长度,那么总数应该是未定义的 (null
)。在那种情况下,使用 Nullable<>
上自动存在的提升 +
。那将是:
.OrderBy(c => c.Episodes.Select(e => e.EpisodeTimeLength)
.Aggregate((TimeSpan?)TimeSpan.Zero, (x, y) => x + y))
或:
.OrderBy(c => c.Episodes.Select(e => e.EpisodeTimeLength)
.Aggregate((x, y) => x + y))
如果您知道 .Episodes
不为空,在这些情况下,您将在最短课程之前自行排序所有总长度为“未定义”的课程。
当然,.Select
并不是严格需要的,因为它们可以内置到 .Aggregate
使用的 lambda 中,例如:
.OrderBy(c => c.Episodes
.Aggregate((TimeSpan?)TimeSpan.Zero, (x, y) => x.EpisodeTimeLength + y.EpisodeTimeLength))
好吧,既然 .OrderBy
就是您所要求的,您不妨按照 fatherOfWine 的小小回答所建议的那样使用 .Ticks
。但是,我在您对他的回答的评论中看到您可能希望保留总课程长度。在这种情况下,您可以只说 .Select
而不是 .OrderBy
,例如:
var allCourseLengths = dbContext.Courses
.Select(c => c.Episodes.Select(e => e.EpisodeTimeLength.Value)
.Aggregate(TimeSpan.Zero, (x, y) => x + y));
等等。