2009-05-22 10 views
19

tengo las siguientes tablas 3 como parte de un simple "elemento etiquetado" esquema:versión de SQL LINQ "IN" declaración

== == Artículos

  • ItemId int
  • varchar Marca
  • Nombre varchar
  • Precio dinero
  • Condición varchar
  • Descr iption varchar
  • poco activo

== == Etiquetas

  • TagId int
  • Nombre varchar
  • poco activo

== == TagMap

  • TagMapId int
  • TagId int (FK)
  • ItemId int (FK)
  • poco activo

Quiero escribir una consulta LINQ para traer de vuelta Los productos que responden a una lista de etiquetas (por ejemplo, TagId = 2,3,4,7). En el contexto de mi aplicación, ejemplos de elementos serían "Monitor de computadora", "Camisa de vestir", "Guitarra", etc. y ejemplos de etiquetas serían "electrónica", "ropa", etc. Normalmente lo haría con un SQL EN Declaración.

+0

Por qué la combinación interna no es preferido aquí? Sabes que si el Context.TagMaps contiene 10 registros, repetirá 36 veces en segundo plano, independientemente de que coincidan o no. – Pankaj

+2

Puede encontrar [consultas SQL en LINQ] (http://www.codeducky.org/sql-queries-in-linq/#where-in) útiles. Es una lista de consultas SQL comunes representadas en LINQ. –

Respuesta

42

Algo así como

var TagIds = new int[] {12, 32, 42}; 

var q = from map in Context.TagMaps 
     where TagIds.Contains(map.TagId) 
     select map.Items; 

debe hacer lo que necesita. Esto generará una cláusula In (12, 32, 42) (o más específicamente una cláusula IN parametrizada si no me equivoco).

+0

entra en juego a través del mapa de selección. Parte del elemento. En SQL, debería unir TagMap a la tabla de elementos. Linq hace eso por ti debido a la relación entre TagMap y Item. Básicamente estás diciendo "encontrar todos los TagMaps que hacen referencia a cualquiera de mis TagIds y devolverme su artículo". Esta consulta LINQ es el mismo que el SQL siguiente:. seleccionar elementos * DE TagMaps INNER JOIN artículos por Item.ItemId = TagMap.ItemId DONDE EN TagMaps.TagId (12,32,24) LINQ toma se ocupa de la parte INNER JOIN para usted, porque sabe cómo pasar de TagMap a Item. –

+0

¿Por qué la unión interna no se prefiere aquí? Sabes que si el 'Context.TagMaps' contiene 10 registros, se repetirá 36 veces en segundo plano, independientemente de si existe coincidencia o no. – Pankaj

+0

La declaración de matriz no es del todo correcta. Combina esta respuesta con la respuesta de @ LukeSchafer a continuación y funcionará. – boilers222

14

matriz dada de los objetos:

var list = new int[] {2,3,4} 

uso:

where list.Contains(tm.TagId) 
+0

No entiendo cómo funcionaría dado el esquema de 3 tablas que tengo. –

1
List<int> tagIds = new List<int>() {2, 3, 4, 7}; 
int tagIdCount = tagIds.Count; 
    // 
// Items that have any of the tags 
// (any item may have any of the tags, not necessarily all of them 
    // 
var ItemsAnyTags = db.Items 
    .Where(item => item.TagMaps 
    .Any(tm => tagIds.Contains(tm.TagId)) 
); 

    // 
// Items that have ALL of the tags 
// (any item may have extra tags that are not mentioned). 
    // 
var ItemIdsForAllTags = db.TagMap 
    .Where(tm => tagIds.Contains(tm.TagId)) 
    .GroupBy(tm => tm.ItemId) 
    .Where(g => g.Count() == tagIdCount) 
    .Select(g => g.Key); 
    // 
var ItemsWithAllTags = db.Items 
    .Where(item => ItemsIdsForAllTags.Contains(item.ItemId)); 

//runs just one query against the database 
List<Item> result = ItemsWithAllTags.ToList(); 
1

Usted puede simplemente utilizar,

var TagIds = {12, 32, 42} 
var prod =entities.TagMaps.Where(tagmaps=> TagIds .Contains(tagmaps.TagId)); 
0
string[] names = {"John", "Cassandra", "Sarah"}; 

var results = (from n in db.Names 
       where names.Contains(n.Name) 
       select n).ToList();