【问题标题】:Why is DateTime breaking my Linq code?为什么 DateTime 会破坏我的 Linq 代码?
【发布时间】:2015-07-08 15:43:26
【问题描述】:

我遇到了一些非常奇怪的事情,涉及 DateTime.Today 和 Linq IEnumerable 结果。我需要在使用 Linq 查询后更改对象列表的 DateTime 属性值并将其设置为 DateTime.Today。发生的事情是,在 foreach 循环结束时,我发现列表为空!怎么会这样?如果我使用 DateTime.Parse,也是如此。有人知道这里发生了什么吗?如果您愿意尝试,这里有一个小程序可以快速测试它:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApplication1
{
    //
    public class TblItem
    {
        public string Learn { get; set; }
        public string Explain { get; set; }
        public string Topic { get; set; }
        public DateTime NextRefresh { get; set; }
        public TblItem()
        {
        }
        public TblItem(string learn, string explain, string topicsid)
        {
            Learn = learn;
            Explain = explain;
            Topic = topicsid;
            NextRefresh = DateTime.Parse("2015-12-01");
        }
    }
    //
    class Program
    {
        static void Main(string[] args)
        {
            string topic = "DEUTSCH_EASY";
            //
            IEnumerable<TblItem> sqlresult = Table()
               .Where(c => ((c.Topic == topic) && (c.NextRefresh > DateTime.Today)))
               .OrderBy(c => c.NextRefresh);
            DebugLog("sqlresult.count(start):" + sqlresult.Count());
            DebugLog("");
            foreach (TblItem item in sqlresult) {
                item.NextRefresh = DateTime.Today;
                DebugLog("sqlresult.count(while):" + sqlresult.Count());
            }
            DebugLog("");
            DebugLog("sqlresult.count(after):" + sqlresult.Count());
        }
        public static List <TblItem> Table()
        {
            string topicSid = "DEUTSCH_EASY";
            return (new TblItem[]{
                new TblItem ("spass", "divertimento", topicSid),
                new TblItem ("prost!", "salute!", topicSid),
                new TblItem ("ich hatte gerne", "mi piacerebbe", topicSid),
                new TblItem ("bitte", "prego", topicSid),
                new TblItem ("das Regen", "la pioggia", topicSid),
            }).ToList<TblItem>();
        }

        public static void DebugLog(string s)
        {
            Console.WriteLine(">>>>"+s);
        }
    }
}

【问题讨论】:

  • NextRefresh的数据类型是什么?你今天有什么数据吗?
  • 你能把这里出现什么错误吗
  • 请注意DateTime.Today.Kind 等于Local,但此语句:NextRefresh = DateTime.Parse("2015-12-01") 返回一个DateTime 对象,其中Kind 等于Unspecified。 MSDN 警告说,在使用 GreaterThan 运算符时,您应该确保两个时间都在同一个时区。
  • @AD.Net 正如你在上面看到的,它是用 DateTime.Parse 初始化的
  • @tinka 编译器没有显示任何错误

标签: c# .net linq datetime


【解决方案1】:

您需要在执行初始 LINQ 查询后调用 .ToList()。 Count() 每次都在处理查询,每次执行的结果都不同,因为您刚刚更改了 NextRefresh 属性。

IEnumerable<TblItem> sqlresult = Table()
               .Where(c => ((c.Topic == topic) && (c.NextRefresh > DateTime.Today)))
               .OrderBy(c => c.NextRefresh).ToList();

【讨论】:

  • 你的胶水确实解决了所有问题,谢谢,我开始为此发疯了
【解决方案2】:

使用ToList() 方法将 IOrderedEnumerable 转换为 IEnumerable 类型。

Table()
    .Where(c => ((c.Topic == topic) && (c.NextRefresh > DateTime.Today)))
               .OrderBy(c => c.NextRefresh).ToList()

【讨论】:

    【解决方案3】:
    Table()
               .Where(c => ((c.Topic == topic) && (c.NextRefresh > DateTime.Today)))
               .OrderBy(c => c.NextRefresh)
    

    不是一个列表,它只是一个在您调用 Count() 时运行和评估的 LINQ 查询。

    Table()
               .Where(c => ((c.Topic == topic) && (c.NextRefresh > DateTime.Today)))
               .OrderBy(c => c.NextRefresh).ToList()
    

    是一个列表

    编辑

    因此,在 foreach 循环中,您更改 NextRefresh,当您再次评估 LINQ 查询时,LINQ 查询的结果会更改。

    【讨论】:

      【解决方案4】:

      你设置好了:item.NextRefresh = DateTime.Today 但查询是c.NextRefresh &gt; DateTime.Today,所以你没有条目符合条件。诀窍是sqlresult 不是固化容器,它只是在每个GetEnumerator(每个 foreach、ToList 等)上重新运行的查询定义。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-02-25
        • 1970-01-01
        • 1970-01-01
        • 2017-12-04
        • 1970-01-01
        • 1970-01-01
        • 2018-02-08
        相关资源
        最近更新 更多