【问题标题】:how to get total of TimeSpan properties inside a Sum() methode in c#?如何在 C# 中的 Sum() 方法中获取 TimeSpan 属性的总数?
【发布时间】:2021-12-08 05:47:49
【问题描述】:

我现在正在做一个 Asp.Net Core 项目。我有一个名为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));

但它们都不起作用,我收到错误:无法将类型“System.TimeSpan”隐式转换为“long”

所以任何人都可以告诉我如何处理它?

【问题讨论】:

  • 你试过c => c.Episodes.Sum(e => e.EpisodeTimeLength.Ticks)吗?
  • 是的,我有,但它说“不包含 'Ticks' 的定义”
  • @juharr 评论似乎是正确的。只需添加空检查,因为我在您的课程中看到 EpisodeTimeLength 可以为空,所以:c => c.Episodes.Sum(e => e.EpisodeTimeLength?.Ticks ?? 0)
  • 您可能必须在客户端进行订购。尝试在OrderBy 之前放置一个AsEnumerable。如果您当时正在执行FirstTake 之类的操作,那当然不是一个好主意。
  • @YomB 有一个版本的Sum 可以处理long,最好使用TotalSeconds,因为Seconds 是整分钟、小时和天的秒数被截断。归根结底,这个问题更多地与将代码翻译成 SQL 有关。

标签: c# linq asp.net-core timespan


【解决方案1】:

您的 TimeSpan 变量可以为空,因此您需要在表达式中使用 Value,并且不需要在 LINQ 方法中创建 TimeSpan 对象。这段代码应该可以工作:

dbContext.Courses.OrderBy( c => c.Episodes.Sum(e=> e.EpisodeTimeLength.Value.Ticks));

【讨论】:

  • 谢谢,效果很好。
  • 但是另一个问题,如果我想将c => c.Episodes.Sum(e=> e.EpisodeTimeLength.Value.Ticks) 分配给一个变量(对于 ewxample:TimeSpan myVar)我该怎么办?
  • 您可以将刻度数传递给 TimeSpan 构造函数: var myVar = new TimeSpan(NumberOfTicks)
【解决方案2】:

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

等等。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-07-13
    • 2016-02-01
    • 2019-02-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-25
    • 1970-01-01
    相关资源
    最近更新 更多