2010-11-11 33 views
1

我有一个项目的集合,其中每个项目都有一个“日期”字段(代码如下)。如何处理LINQ中的源数据更改?

我想填补使用LINQ的集合中日期中的任何空白。特别是,我希望得到的序列包含原始序列中第一天和最后一天之间的所有天数。

除此之外,我的结果LINQ查询应该能够处理原始序列的任何修改。那就是我无法提前计算最小和最大日期。

所以我试了下面的代码,但它试图计算序列的最小值和最大值时失败。我正在寻找一个“懒惰”的选择。

感谢您的帮助 康斯坦丁


using System; 
using System.Collections.Generic; 
using System.Collections.ObjectModel; 
using System.Linq; 

namespace consapp 
{ 
    class C 
    { 
     public DateTime date; 
     public int? value; 
    } 

    static class Program 
    { 
     static IEnumerable<C> dates(DateTime d0, DateTime d1) 
     { 
      for (var d = d0; d <= d1; d = d.AddDays(1)) 
      { 
       yield return new C { date = d }; 
      } 
     } 

     static void Main(string[] args) 
     { 
      var xs = new ObservableCollection<C>(); 

      var q = from d in dates(xs.Min(y => y.date), xs.Max(y => y.date)) 
        join x in xs on d.date equals x.date into js 
        from j in js.DefaultIfEmpty() 
        orderby d.date 
        select new { date = d.date, value = j != null ? j.value : null }; 

      xs.Add(new C { date = DateTime.Parse("11/10/11") }); 
      xs.Add(new C { date = DateTime.Parse("02/02/11") }); 
      xs.Add(new C { date = DateTime.Parse("11/24/11") }); 
      xs.Add(new C { date = DateTime.Parse("09/09/11") }); 
      xs.Add(new C { date = DateTime.Parse("11/10/11") }); 

      foreach (var x in q) 
      { 
       Console.WriteLine(x.date.ToShortDateString()); 
      } 
     } 
    } 
} 
+0

你好konstantin,因为Stackoverflow是一个社区编辑的QnA列表,你应该编辑你的问题标题。或者你对“需要linq帮助”这个问题期待什么样的答案?问候 – Zeemee 2010-11-11 16:08:41

+0

@穆尔穆特:谢谢,希望新的主题行更具体 – akonsu 2010-11-11 16:15:34

回答

1

我不是绝对肯定,但:

var q = from d in dates(xs.Min(y => y.date), xs.Max(y => y.date)) 

我相信“日期”方法将立即被调用,并且LINQ查询的其余部分(包括来自dates()本身的迭代器)将围绕该方法的结果构建。所以你将不得不预先在你感兴趣的数据中填充xs

这是因为LINQ本质上是通过将可枚举枚举包装在其他枚举类型中工作的。为了做到这一点,它必须从一个枚举开始。为了做到这一点,它必须调用order()方法,其中要求立即提供其参数,以便它可以接收将要包装在其他枚举中的可枚举对象。因此,当达到该行代码时,将调用xs.Minxs.Max方法,但实际上不会处理查询中的任何其他内容。

解决方法是让您的dates()方法实际上收到ObservableCollection并自行呼叫Min/Max。因为这将发生在生成的迭代器中,所以这些调用的执行将按照您的预期推迟。

+0

将整个集合传递给dates()作品。谢谢。 – akonsu 2010-11-11 16:18:56

0

标准LINQ实现了基于IEnumerable<T>不能处理作为ObservableCollection改变这样的数据源。您的示例失败的原因是它会尝试评估数据源(并在定义查询时调用dates函数和MinMax运算符)(但该数据源在该点上不包含任何数据)。

  • 一种选择是使用替代的LINQ实现与ObservableCollection工作,并且可以自动更新结果的来源发生变化时。据我所知Bindable LINQ项目应该能够做到这一点。

  • 另一个(更简单的)选项是当您知道数据源已更改时,将查询转变为方法并重复调用方法(以更新结果)。你不得不做出ObservableCollection私有字段和方法只会运行使用当前存储在集合中的数据:

    private ObservableCollection source; 
    void UpdateResults() { 
        var q = /* The query goes here */ 
        // Do something with the result of the query 
    } 
    
+0

感谢您的参考。我只是试着在那个页面中的示例代码,他们说没有在屏幕上显示任何东西,它似乎工作。我正在使用.net 4.0。看来他们现在在LINQ中有这种能力,不是吗? – akonsu 2010-11-11 16:11:52

相关问题