2013-01-17 49 views
0

我有一个IEnumerable<T>,它有一个Created字段,这是一个日期。
每个日期可能有多个T,有时在给定日期没有T创建包含丢失键的分组

当前我将这些日期按照日期分组,这些日期至少包含一个日期,其中包含至少一个TT

但是我想要的是,我可以将其用作查询的一部分,这将使我获得某个范围内的所有日期,而不管在给定日期是否有任何T

目前代码:

var adjustments = DAL.GetAdjustmentsInDateRange(Start, End); 

from adjustment in adjustments 
group adjustment by adjustment.Created.Date into adjustmentsByDay 
orderby adjustmentsByDay.Key descending 
select .... 

这里,adjustmentsByDay没有StartEnd之间的所有日期。我想要的是它包含它们,没有任何元素。

我该怎么做?

回答

1

我已经把通用的LINQ到对象扩展方法插入缺失的东西放进顺序:

public static IEnumerable<T> InsertMissing<T, U>(this IEnumerable<T> source, 
    Func<T, U> key, Func<U, U> increment, Func<U, T> create) 
{ 
    bool first = true; 
    U last = default(U); 

    foreach (var ig in source) 
    { 
     U current = key(ig); 

     if (first) 
     { 
      first = false; 
      last = current; 
      yield return ig; 
      continue; 
     } 

     while (!(last = increment(last)).Equals(current)) 
     { 
      yield return create(last); 
     } 

     yield return ig; 
    } 
} 

你还需要的IGrouping自定义实现:

class EmptyGrouping<K, E> : IGrouping<K, E> { 
    public K Key { get; set; } 

    public IEnumerator<E> GetEnumerator() { 
     return Enumerable.Empty<E>().GetEnumerator(); 
    } 

    IEnumerator IEnumerable.GetEnumerator() { 
     return this.GetEnumerator(); 
    } 
} 

然后,你将需要orderby后结束你的查询,使用该调用遵循它,然后把你的select算账:

var allGroups = query.InsertMissing(
    // Key selector 
    g => g.Key, 
    // Get next desired key from current key 
    d => d.AddDays(-1), 
    // Create item for missing key 
    d => new EmptyGrouping<DateTime,YourAdjustmentType>{ Key = d }); 

就会失控,如果你的钥匙是没有顺序的,或者其中一个不在正确的位置(例如,在你的情况下,不是在午夜)。

这样做的好处是不需要对原始源进行多个查询来确定最小/最大值以生成密钥列表,然后再进一步查询以加入并获取数据。

+0

好!喜欢查询扩展。 –

2

你可以离开分组加盟之前所有日期的列表的调整,像这样:

var adjustments = DAL.GetAdjustmentsInDateRange(Start, End); 
// Get all unique dates in time span 
IEnumerable<DateTime> dates = GetAllDates(Start, End); 

var query = (from date in dates 
       join adjustment in adjustments 
        on date.Date equals adjustment.Created.Date into a 
       from adjustment in a.DefaultIfEmpty() 
       select new {date.Date, adjustment} 
       ).GroupBy(i=>i.Date).OrderBy(g=>g.Key); 
+0

这看起来不错,但此刻我在群组中按行发生错误,因为'adjust'为'null'(我已经离开那条线并且在相同的位置)。 –

+0

对不起,如果有语法错误。参考Linq 101,左外连接是最后一个例子:http://code.msdn.microsoft.com/101-LINQ-Samples-3fb9811b –

+0

我现在更新了我的答案,但是组和顺序是在方法中语法而不是查询语法。这个解决方案适用于我,假设你可以首先创建一个所有日期列表,包括'开始'和'结束' –