2009-05-22 10 views
19

ho i seguenti 3 tabelle come parte di un semplice "voce di codifica" schema:versione di SQL LINQ "IN" dichiarazione

Articoli == ==

  • ItemId int
  • Marca varchar
  • Nome varchar
  • Prezzo soldi
  • Condizione varchar
  • Descr iption varchar
  • po attivo

== == Tag

  • TagID int
  • Nome varchar
  • po attivo

== == TagMap

  • TagMapId int
  • TagID int (FK)
  • ItemId int (FK)
  • po attivo

Voglio scrivere una query LINQ per portare indietro Articoli che corrispondono a un elenco di tag (ad esempio TagId = 2,3,4,7). Nel mio contesto applicativo, esempi di elementi sarebbero "Computer Monitor", "Dress Shirt", "Guitar", ecc. Ed esempi di tag sarebbero "elettronica", "abbigliamento", ecc. Normalmente lo farei con un SQL IN Dichiarazione.

+0

Perché l'interno join non è preferito qui? Sai se Context.TagMaps contiene 10 record, itererà 36 volte in background, indipendentemente dal fatto che ci sia o meno una corrispondenza. – Pankaj

+2

È possibile trovare [query SQL in LINQ] (http://www.codeducky.org/sql-queries-in-linq/#where-in) utili. È un elenco di query SQL comuni rappresentate in LINQ. –

risposta

42

Qualcosa di simile

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

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

dovrebbe fare quello che ti serve. Questo genererà una clausola In (12, 32, 42) (o più specificatamente una clausola IN parametrizzata, se non mi sbaglio).

+0

entra in gioco attraverso la mappa selezionata. Oggetto parte. In SQL dovresti unire TagMap alla tabella Item. Linq lo fa per te a causa della relazione tra TagMap e Item. In pratica stai dicendo "trova tutti i TagMaps che fanno riferimento ai miei TagID e restituiscimi il loro articolo". Questa query LINQ è lo stesso il seguente SQL:. Articoli SELECT * FROM TagMaps INNER JOIN articoli Sul Item.ItemId = TagMap.ItemId DOVE TagMaps.TagId IN (12,32,24) Linq prende cura la parte INNER JOIN per te, perché sa come passare da TagMap a Item. –

+0

Perché il join interno non è preferito qui? Sai se il 'Context.TagMaps' contiene 10 record, itererà 36 volte in background, indipendentemente dal fatto che ci sia o meno una corrispondenza. – Pankaj

+0

La dichiarazione dell'array non è del tutto corretta. Combina questa risposta con la risposta di @ LukeSchafer qui sotto e funzionerà. – boilers222

14

dato array di oggetti:

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

uso:

where list.Contains(tm.TagId) 
+0

Non capisco come funzionerebbe dato lo schema di 3 tabelle che ho. –

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

Si può semplicemente utilizzare,

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();