2009-07-05 24 views
33

lo tanto, estoy tratando de devolver una colección de personas cuyo ID está contenido dentro de una colección creada localmente de identificadores (IQueryable)Trabajando LinqToSQls "consultas con colecciones locales no son compatibles" excepción

cuando especifico " colección localmente creada ", quiero decir que la colección Ids no proviene de una consulta LinqToSql y se ha creado programáticamente (en función de la entrada del usuario). Mi consulta es el siguiente:

var qry = from p in DBContext.People 
        where Ids.Contains(p.ID) 
        select p.ID; 

Esto hace que la siguiente excepción ...

"consultas con colecciones locales no son compatibles"

¿Cómo puedo encontrar todas las personas con un identificador que está contenido dentro de mi colección Ids creada localmente?

¿Es posible usar LinqToSql?

Respuesta

34

Si Ids es una lista, matriz o similar, L2S se traducirá en un contiene.

Si Ids es un IQueryable, simplemente conviértalo en una lista antes de usarlo en la consulta. Por ejemplo:

List<int> listOfIDs = IDs.ToList(); 
var query = 
from st in dc.SomeTable 
where listOfIDs.Contains(st.ID) 
select ..... 
+2

Creo que la solución a su problema es más matizada que esta respuesta. Estoy usando la misma construcción (un método Contiene en un IQueryable en una cláusula WHERE) con éxito, y LINQ to SQL lo traduce en una cláusula WHERE EXISTS en la consulta SQL. Parece que funciona en algunas situaciones y otras no, por lo que debe publicar cómo obtiene su Ids IQueryable, ya que puede arrojar algo de luz sobre el tema. –

+1

@jmbledsoe si mi respuesta no fue lo suficientemente clara: L2S espera que un IEnumerable local (no un IQueryable diferido) pase a Enumerable.Contains. Si le pasa una consulta local, no se puede traducir a una consulta SQL. Si le pasa una lista/matriz/etc, entonces se puede traducir a una cláusula SQL "where ... in (x, y, ..., n)". – KristoferA

+2

Creo que veo lo que estás diciendo: - Al pasar una lista/matriz/etc. está bien b/c generará una cláusula WHERE ... IN. - Pasar un IQueryable diferido es ACEPTABLE b/c integrará con la consulta diferida actual. - Pasar un IEnumerable local NO está bien, pero puede simplemente .ToList() y estará bien. –

26

Estaba luchando con este problema también. Resuelto mi problema con el uso Cualquier() en lugar

people.Where(x => ids.Any(id => id == x.ID)) 
+0

@maxlego Y el SQL generado es descendiente. Gracias –

0

Lo siento, pero las respuestas aquí no funcionó para mí, ya que estoy haciendo tipos dinámicos más adelante.

Lo que hice fue utilizar "UNION" en un bucle que funciona muy bien. He aquí cómo:

var firstID = cityList.First().id; 
var cities = dc.zs_Cities.Where(c => c.id == firstID); 
foreach(var c in cityList) 
{ 
    var tempCity = c; 
    cities = cities.Union(dc.zs_Cities.Where(cty => cty.id == tempCity.id)); 
} 
Cuestiones relacionadas