2012-01-17 5 views
6

Estoy migrando parte de nuestro código de LINQ-to-SQL a Entity Framework. Anteriormente, cuando se ejecutaba en un límite de 2100 parámetros de SQL Server (descrito here), utilicé la solución provista por Marc Gravell here. Como se indica en su propia respuesta, no funciona con Entity Framework.Marco de Entity Hitting 2100 Límite de parámetro

Soy muy inexperto con Expressions para saber por dónde empezar, pero lo que busco es básicamente el mismo método de extensión pero aplicable a Entity Framework. Gracias de antemano por cualquier ayuda que pueda brindar.

+1

Crear una consulta que requiera más de 2100 elementos estáticamente definidos para la instrucción 'IN' (que es la parte del contador de' Contains') no parece una aproximación correcta. Tal operación debe manejarse completamente en DB sin necesidad de pasar datos del cliente. –

+0

Entiendo su preocupación, pero ciertamente hay casos en los que * todos * los datos requeridos no estarán en la base de datos. Definitivamente hay alternativas para pasar una lista tan grande de parámetros, pero este simple resumen resulta extremadamente flexible para la forma en que nos gustaría usarlo (y el 99% del tiempo no será necesario usarlo). – Ocelot20

Respuesta

13

El problema del límite de 2100 parámetros no existe en EF.

He realizado una prueba en the AdventureWorks database (en SQL Express 2008 R2): Estoy tratando de obtener todos los productos donde ProductCategoryId está en el rango de valores (1, 2, 3).

Usando LINQ, la generada WHERE cláusula SQL tiene este aspecto:

WHERE [t0].[ProductCategoryID] IN (@p0, @p1, @p2) 
-- @p0: Input Int (Size = -1; Prec = 0; Scale = 0) [1] 
-- @p1: Input Int (Size = -1; Prec = 0; Scale = 0) [2] 
-- @p2: Input Int (Size = -1; Prec = 0; Scale = 0) [3] 

(que conduce a la cuestión número de parámetro max), mientras que con EF 4.0 se ve así:

WHERE [Extent1].[ProductCategoryID] IN (1,2,3) 

A continuación, he probado esto con EF para obtener una lista de 3000 valores:

var categoryList = Enumerable.Range(1, 3000).Select(i => (int?)i).ToArray(); 

using (var aw = new AdventureWorksEntities()) 
{ 
    var products = aw.Products 
     .Where(p => categoryList.Contains(p.ProductCategoryID)) 
     .ToList(); 
} 

Mientras esto es extremadamente ineficiente, funciona y produce el resultado esperado.

Sin embargo, también es posible utilizar el InRange extensión provided by Marc Gravell con EF, utilizando también la LINQKit library, así:

using (var aw = new AdventureWorksEntities()) 
{ 
    var products = aw.Products 
     .AsExpandable() 
     .InRange(p => p.ProductCategoryID, 1000, categoryList) 
     .ToList(); 
} 

(la extensión AsExpandable se define en LINQKit)

Esto produce el resultado esperado (ejecuta la consulta en fragmentos) y, dependiendo de la cantidad de elementos en la lista y el tamaño del fragmento, puede ser mucho más eficiente que la solución no fragmentada.

Cuestiones relacionadas