Using C#, NHibernate, NHibernate to LINQ. Using NHibernate to LINQ, I do not have the JOIN functionality. I can not use QueryOver either.
I have a LINQ query that co
You can Union()
the data from your query with dummy items that you create in memory. For example:
var query4 = query3.ToList(); // Prevent multiple execution.
var startDate = DateTime.Today.AddDays(-99);
var emptyData = Enumerable.Range(1,100).Select (i =>
new ReferrerChart
{
Date = startDate.AddDays(i),
LeadsCount = 0,
SalesCount = 0
});
var result = query4 .Union(
emptyData
.Where(e => !query4.Select(x => x.Date).Contains(e.Date)))
.OrderBy(x => x.Date);
There are two things I would change in your LINQ Query, I'd include the null dates
.Where(x => x.Created <= toDate.Value && x.Created >= fromDate.Value)
becomes something like
.Where(x => x.Created.Date == null || (x.Created <= toDate.Value && x.Created >= fromDate.Value))
My other pointer would be that your .GroupBy requires a x.Created.Date, use of IsNull or similar function to set the value here to a value regardless of whether the entry is Null
E.g. (x.Created == null ? "" : x.Created.ToString("yyyyMMdd"))
(I apologize but I'm not on my development PC at this moment in time so can't definitively state the correct code)
There's a great way to do it by implementing an extension method for IEnumerable<IGrouping<TKey, TElement>>
(the type that is returned from GroupBy
). In my humble opinion it's the best approach for a number of reasons:
.ToList()
also accomplishes that, but at the price of eager evaluation),GroupBy
,public static IEnumerable<IGrouping<TKey, TElement>> Fill<TKey, TElement>(this IEnumerable<IGrouping<TKey, TElement>> groups, IEnumerable<TKey> filling)
{
List<TKey> keys = filling.ToList();
foreach (var g in groups)
{
if(keys.Contains(g.Key))
keys.Remove(g.Key);
yield return g;
}
foreach(var k in keys)
yield return new EmptyGrouping<TKey, TElement>(k);
}
class EmptyGrouping<TKey, TElement> : List<TElement>, IGrouping<TKey, TElement>
{
public TKey Key { get; set; }
public EmptyGrouping(TKey key)
{
this.Key = key;
}
}
Random rand = new Random();
var results = Enumerable.Repeat(0, 5) // Give us five
.Select(i => rand.Next(100)) // Random numbers 0 - 99
.GroupBy(r => r.Dump("Calculating group for:") / 10) // Group by tens (0, 10, 20, 30, 40...)
.Fill(Enumerable.Range(0, 10)) // Fill aby missing tens
.OrderBy(g => g.Key); // Sort
@"Anything above = eager evaluations.
Anything below = lazy evaluations.".Dump();
results.Dump();
(Five integers on top are printed from inside the query when it's being evaluated. As you can see, there was only one calculation pass).