2011-07-08 1 views
1

Je vais avoir des problèmes avec LINQ à requête SQL dans le scénario suivant:LINQ to SQL requête sur le pont Tableau

  • J'ai des éléments qui ont "Tags" appliqués par une table de bridge.
  • J'essaie de filtrer une liste d'éléments dans un sous-ensemble qui contient l'ensemble d'un ensemble de balises spécifié et renvoie la liste filtrée d'éléments en tant que résultat de la requête.

tables impliquées:

Item (ItemId, Name, ...other fields) 
Tag (TagId, TagName) 
Item_Tag(ItemId, TagId) 

À titre d'exemple, si j'avais une liste d'articles avec des tags:

  • Item1 w/(Tag1, tag2)
  • Item2 w/(Tag1, Tag2)
  • Article3 avec (Tag1)

et je voulais obtenir tous les éléments où l'élément a à la fois Tag1 et Tag2 où l'exigence de filtre est fourni comme un int [] des tagIds requis.

En supposant que l'ID d'élément et d'étiquette correspond au numéro à la fin du nom. Le filtre pour cet exemple serait:

int[] tagFilterConditions = int[2]{1, 2}; 

var query = from i in itemList 
//define filter here 

où le résultat serait: Item1, Item2 (exclut le point 3 b/c il est pas marqué avec Tag1 ET Tag2)

Je vais avoir J'ai du mal à trouver comment combiner ces tables pour appliquer ce filtre sur la liste des sources, j'ai essayé d'utiliser un predicate builder et plusieurs jointures, mais je n'arrive pas à obtenir les résultats corrects.

Merci, pour toute aide ...

+0

Avez-vous créé mappages (clés étrangères) entre les tables, de sorte que vous pourriez utiliser 'item.Tags' (ou' item.Item_Tags') au lieu d'avoir à interroger explicitement la table 'Item_Tag'? –

Répondre

0
// Query for all the items in the list 
int[] itemIds = itemList.Select(item => item.ItemId).AsArray(); 
var query = 
    db.Item.Where(item => 
     itemIds.Contains(item.ItemId)); 

// Apply each tag condition 
foreach (int tagid in tagFilterConditions) 
{ 
    int temp = tagid; 
    query = query.Where(item => 
     db.Item_Tag.Exists(item_tag => 
      item_tag.ItemId == item.ItemId && item_tag.TagId == temp))); 
} 
+0

Merci, je me suis fait raccrocher en essayant de faire fonctionner quelque chose dans une seule requête linq ... J'ai ajouté la relation de clé étrangère comme vous l'avez mentionné ci-dessus et j'ai obtenu la requête suivante. clarté. – jrob

0

Je pense que la réponse à votre question est .Contains(): http://blog.wekeroad.com/2008/02/27/creating-in-queries-with-linq-to-sql

Voici ce que je pense est l'extrait pertinent de ce site à votre question:

int[] productList = new int[] { 1, 2, 3, 4 }; 

var myProducts = from p in db.Products 
      where productList.Contains(p.ProductID) 
      select p; 

Espérons que cela aide!

+0

J'ai essayé divers scénarios using contient sauf que j'essaye de comparer est dans la table de pont et pas dans le "Items" la table elle-même .. contient aussi() ne semble pas faire une comparaison ET où tous les articles dans le le tableau doit exister. – jrob

+0

Mon mauvais, j'ai totalement raté l'exigence ET ...Essayer de penser à des alternatives ... Le chargement de tout le contenu de la table de bridge dans la mémoire locale est-il une option? Il semble que ce soit une table de balises entières, alors pourriez-vous le mettre dans un tableau local? Cela éliminerait au moins une étrange bizarrerie LINQ-to-SQL si vous avez besoin d'utiliser une fonctionnalité C# qui ne se traduit pas par SQL. –

0

Here est quelques sql.

et here est le LinqToSql ..

0

Got la requête suivante au travail en utilisant un type anonyme après avoir défini les relations propres clés étrangères la requête a été adaptée d'une réponse sur this question.

//the tagId's that the item in itemList must have 
int[] tagFilterConditions = int[2]{1, 2}; 

var query = 
    itemList.Select(i=> new { i, itemTags= item.Item_Tags.Select(it=> it.TagId)}) 
      .Where(x=> tagFilterConditions.All(t=> x.itemTags.Contains(t))) 
      .Select(x=> x.s);