views:

104

answers:

2

I'm using C# 3.5 and EntityFramework. I have a list of items in the database that contain interest rates. Unfortunately this list only contains the Effective Start Date. I need to query this list for all items within a range.

However, I can't see a way to do this without querying the database twice. (Although I'm wondering if delayed execution with EntityFramework is making only one call.) Regardless, I'm wondering if I can do this without using my context twice.

internal IQueryable<Interest> GetInterests(DateTime startDate, DateTime endDate)  {
    var FirstDate = Context.All().Where(x => x.START_DATE < startDate).Max(x => x.START_DATE);
    IQueryable<Interest> listOfItems = Context.All().Where(x => x.START_DATE >= FirstDate && x.START_DATE <= endDate);
    return listOfItems;
}
+2  A: 

Hey,

If you could use a LINQ query, you can use let to do this:

(from c in dbContext.Table
let firstdate = dbContext.Table.Max(i => c.StartDate < startDate)
where c.StartDate >= firstdate
and c.StartDate <= enddate
select c)

I'm not sure if the max will work this way, so you may need to alternatively do:

(from c in dbContext.Table
let firstdate = dbContext.Table.Select(i => i.StartDate).Max(i => c.StartDate < i)
where c.StartDate >= firstdate
and c.StartDate <= enddate
select c)

Something like that.

Brian
There is no c.EndDate - itchi only has one DateTime value per record - a start value.
Hightechrider
Yeah, I actually wrote it like this originally, and then converted it to lambda syntax. But the two calls to context bothered me.
itchi
@Hightechrider thanks, updated the post. @itchi Extension method was for sure doable, but LINQ queries can be more readable IMHO, plus the let does a subquery, instead of a separate query.
Brian
+1  A: 

I haven't tried this on EF but on Linq to objects it works fine:

var result = source
  .OrderBy(x => x.start)
  .GroupBy(x => x.start < startDate)
  .SelectMany((x, i) => i == 0 ? new[] {new { value = x.Last().value, start = x.Last().start }} : x.Where(y => y.start < endDate));

The issue is that C# LINQ is missing an operator which gives you access to the previous item in a sequence. F# apparently can handle this. Workarounds involved either a GroupBy or an Aggregate operation. In this case, GroupBy can handle it.

It's not pretty and I wouldn't recommend using it over the two phase approach.

Hightechrider
Thanks, C# LINQ missing an operator gets the answer for showing me why I can't write this the way I want to. F# is an interesting thought.
itchi