Doesn't EF support Take
and Skip
?
The beauty of LINQ was that you could describe this complex sort criteria and the just page the result by saying q.Skip(50).Take(50)
. That would take you the second page if each page displayed 50 results. And it's of course translated to effective T-SQL that uses the ROW_NUMBER
window function to instruct the database to seek out the result using the order you specified.
You can even have a very complex query with lots of filters. The end result is still manageable as you'll either have rows or you won't. All you need to think about is that the result could be empty.
A note about identity, as Ladislav pointed out the order is not guaranteed between entries of the exact same sort key (i.e. Date and Time both being null). So what you do is that you add an identity column which is your least important sort column. A log table/entity that doesn't have an identity can be somewhat argued to be improperly designed because the growth of the data is unpredictable when Date and Time can be null. It will result in bad page splits. The rule of thumb is that a table should have a narrow and unique clustering primary key. The identity column fits this quite nicely. It will also ensure that inserts are fast operations something your log table will appreciate.
With the help of a view you can put the order by and row_number stuff in plain T-SQL then query that using EF like this:
var q = from x in source
join y in source on x.RowNumber equals y.RowNumber - 1 into prev
join z in source on x.RowNumber equals z.RowNumber + 1 into next
from p in prev.DefaultIfEmpty()
from n in next.DefaultIfEmpty()
select new { Current = x, Previous = p, Next = n }
;
...or possibly:
var q = from x in source
join y in source on x.RowNumber equals y.RowNumber - 1 into prev
join z in source on x.RowNumber equals z.RowNumber + 1 into next
select new {
Current = x,
Previous = prev.DefaultIfEmpty(),
Next = next.DefaultIfEmpty()
}
;