I have a search function that uses the Entity Framework. One of the things you can search by is a date range. You might say something like "where Start Date is between SearchStart and Search End". It isn't that difficult to write in linq syntax, but it can get pretty verbose when you have many different date parameters to search by.
I have an extension method on DateTime that basically checks of the date is contained between a StartDate and an EndDate. I use this in other places where EF isn't an issue, but I would also like to use it with EF queries. I am creating the query dynamically by applying additional WHERE clauses before doing a ToList (which will try to run the query).
As I had expected, using the extension method throws an exception: "LINQ to Entities does not recognize the method 'Boolean IsBetween(System.DateTime, System.DateTime, System.DateTime)' method, and this method cannot be translated into a store expression."
I understand that Linq to Entities has no way of knowing what IsBetween translates to in Sql, but is there a way for me to give it instructions? I tried searching online for the answer, but it wasn't very helpful. If there some attribute I can add to the extension method or some way I can update the EF configuration?
I am guessing not, but I don't want to assume without asking.
Thanks!
UPDATE: Adding extension method code
public static bool IsBetween(this DateTime date , DateTime start, DateTime end)
{
return (date >= start && date < end);
}
You can use
DbFunctions
class to generateBETWEEN
sql statementhttp://msdn.microsoft.com/en-us/library/system.data.entity.dbfunctions(v=vs.113).aspx
It's called
EntityFunctions
in versions of EF earlier than 6.0.Here is a totally generic approach, similar to what danludig's answer is doing but diving more deep in and hand building Expression trees to make it work.
We are not teaching Entity Framework how to read a new expression, instead we are breaking the expression in to its component parts to something Entity Framework already knows how to read.
It generates the following SQL
Using this below program.
Here is a utility that can convert a generic expression and map it to your specific object. This allows you to write your expression as
date => date >= start && date < end
and just pass it in to the converter to map the necessary columns. You will need to pass in one mapping per parameter in your original lambada.Here is a simple test program I used to test it out, it generates well formed queries with parameters passed in where they should be.
You can see this also fixes the "constant string" problem I was having in the first example, the DateTimes are now passed in as parameters.
Usage:
Extension method
Now you don't get full reusage of your other extension method here. However, you can reuse this new extension method in several other queries. Just invoke .InBetween on your queryable and pass the args.
Here is another way to do it: