I'm attempting to refactor a cumbersome LINQ-to-SQL data layer with an entity framework one. The database schema behind the model is big and a typical query might have 20 to 30 Includes. The EF generates massive SQL statements for such queries, the biggest so far has been 4k lines, but they still execute in a timely fashion so that's not a problem.
The problem is that the EF takes a long time, up to 4 or 5 seconds to generate the query. To overcome that I've used CompileQuery. The problem then is that the existing L2S datalayer has a lot of filters that can be applied to a query depending on user input. A single value in those filters needs to be set at runtime.
The code below doesn't work because the initial static values get compiled into the query but it demonstrates what I'm attempting to do.
public static class DataLayer
{
static Func<MyEntities, int, IQueryable<Prescription>> compiledQuery;
static int? FilterHpID;
static Expression<Func<Prescription, bool>> filter1 = x => (FilterHpID == null || x.Prescriber.HPID == FilterHpID);
static DateTime? FilterDateTime;
static Expression<Func<Prescription, bool>> filter2 = x => (FilterDateTime == null || x.DateTimeDispensed > FilterDateTime);
public static List<Prescription> Get(int patientID, int? hpID, DateTime? dispensed)
{
FilterHpID = hpID;
FilterDateTime = dispensed;
if (compiledQuery == null)
{
compiledQuery = System.Data.Objects.CompiledQuery.Compile((MyEntities entities, int id) =>
(from pre in entities.Prescription
where pre.PatientID == id
select pre)
.Where(filter1)
.Where(filter2));
}
using (MyEntities entities = new MyEntities())
{
return compiledQuery(entities, patientID).ToList();
}
}
}
Is there any way I can include my filter expressions in the compiled query AND be able to set values on the filter expressions when executing the query?