我已经组合了一个通用的 LINQ-to-objects 扩展方法来将缺失的东西插入到一个序列中:
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 });
如果您的钥匙没有订购或者其中一个钥匙没有放在正确的位置(例如,在您的情况下,不是在午夜),这将变得混乱。
这样做的好处是不需要对原始源进行多次查询来确定最小值/最大值以生成键列表,然后再进行进一步的查询来连接和获取数据。