When one creates a linq query as:
var ids = new List<int> { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
var q = from r in context.Table
where ids.Contains(r.Id)
select r;
for use with EF, it generates the T-SQL similar to
SELECT ... FROM Table
WHERE Id IN ( 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 )
In general this is what I expect, though it does seem to mess up the ‘Query plan compilation’ in that each query is different, and thus needs to be compiled before being executed.
Since EF is otherwise very good at using variables ((@p_linq_) to avoid this, it does not (by default) do this for these sort of queries.
Is it at all possible to avoid this?
Table-Valued parameters spring to mind, but that is not yet supported.
btw: in real life the queries are a lot more complicated and the number of items in the ids list is a lot longer, but still needed to filter out the data. We do not want to filter on the ‘client’.
I implemented this once by modifying the TSQL generated by EF to emit an xml string parameter which was evaluated as a table valued parameter in the query itself.
The impact of this wasn’t as grand as I had hoped and while performance improved vastly in some areas, other queries that previously performed very well, now performed terribly.
Ultimately, we ended up switching the implementation to an opt-in approach by having a custom Contains method that was mapped as a model defined function (http://blogs.msdn.com/b/efdesign/archive/2009/01/07/model-defined-functions.aspx). So the usage was like
and this generated an something like the following sql (which avoided the query plan recompiling each time).
This approach also has the added benefit of getting around the 2100 parameter limitation…