2009-09-06 5 views
0

Bonne journée!Dans la suite de questions "Schéma DB pour stocker les enregistrements étiquetés" - comment sélectionner la liste des éléments avec des étiquettes?

Il y a beaucoup de questions comment stocker les tags dans DB ici sur stackoverflow, je décide finalement d'utiliser l'approche Toxi (articles balises table, table et many-to-many table intermédiaire) http://www.pui.ch/phred/archives/2005/04/tags-database-schemas.html

Je veux afficher une liste de 20 à 50 éléments marqués sur une page chacun avec la liste de ses balises (j'utilise LINQ2SQL dans ASP.NET 3.5).

Je vois quelques options:

  1. première requête pour la liste des éléments que l'exécution requête pour chaque élément pour sélectionner les balises pour chaque élément - semble être lent, mais la mise en cache au niveau de l'application peut améliorer la situation.

  2. Dénormaliser la table des éléments et stocker la liste des tags pour l'élément dans le champ de texte du tableau "items".

Cependant les deux options me semblent mauvaises, peut-être qu'il me manque quelque chose?

Merci d'avance!

Répondre

0

2KLE: merci, je l'ai. Le résultat de cette requête est une ligne pour chaque variable (les données de l'élément sont dupliquées), de toute façon il est nécessaire de traiter le jeu de résultats dans le code de l'application. Ai-je raison? Pour LINQ 2 SQL, j'ai utilisé DataLoadOptions pour spécifier les données associées que je veux charger. Voici un exemple de code généré par LINQ2SQL pour sélectionner tous les éléments avec toutes les balises.

Veuillez noter que la table Items est appelée Snippets dans mon exemple (nous avons donc des Snippets, Tags et SnippetsTags). Une autre chose à noter est que LINQ2SQL ne supporte pas les relations many-to-many, donc il existe une classe d'entité pour la table intermédiaire (SnippetsTag). Voici le code C#:

  using (SnippetsDataContext context = UtilsLinq.CreateContext()) 
     { 
      DataLoadOptions dl = new DataLoadOptions(); 
      dl.LoadWith<Snippet>(s => s.SnippetsTags); 
      dl.LoadWith<SnippetsTag>(st => st.Tag); 
      context.LoadOptions = dl; 
      var result = (from s in context.Snippets 
          select s).ToList(); 

      string x = result.First().SnippetsTags.First().Tag.Title; 
     } 

Voici une SQL qui génère LINQ to SQL:

SELECT [t0].[Id], [t0].[Title], [t0].[Text], [t0].[Created], [t1].[Id] AS [Id2], [t1].[TagId], [t1].[SnippetId], [t2].[Id] AS [Id3], [t2].[Title] AS [Title2], (
    SELECT COUNT(*) 
    FROM [dbo].[SnippetsTags] AS [t3] 
    INNER JOIN [dbo].[Tags] AS [t4] ON [t4].[Id] = [t3].[TagId] 
    WHERE [t3].[SnippetId] = [t0].[Id] 
    ) AS [value] 
FROM [dbo].[Snippets] AS [t0] 
LEFT OUTER JOIN ([dbo].[SnippetsTags] AS [t1] 
    INNER JOIN [dbo].[Tags] AS [t2] ON [t2].[Id] = [t1].[TagId]) ON [t1].[SnippetId] = [t0].[Id] 
ORDER BY [t0].[Id], [t1].[Id], [t2].[Id] 
0

Je ne recommande pas l'option 2 car cela compliquerait trop les tentatives d'isoler une étiquette ou un groupe de balises. Ma recommandation serait de laisser le modèle de données tel quel (ITEMS, TAGS, ITEM_TAGS_XREF), et interroger une VIEW qui contiendrait une colonne calculée contenant la liste des balises. Si vous avez mentionné la base de données que vous utilisez, nous pouvons fournir la requête qui construira une chaîne délimitée par une virgule/etc des balises auxquelles un élément est associé.

En supposant que les clés primaires et étrangères sont configurées en conséquence, les performances ne doivent pas être mauvaises - est-il possible que le décalage se produise dans la couche application?

+0

Merci pour la réponse détaillée! Pouvez-vous partager un pseudo code pour cette vue? La colonne calculée doit-elle exécuter la sous-requête corelated pour chaque ligne sur la table de balises?Est-ce acceptable en termes de performance? Merci! – artvolk

+0

Quelle base de données utilisez-vous? Je ne suis pas familier avec LINQ. Je suis sûr que la requête pourrait être construite pour utiliser une requête JOIN plutôt que corrélée. –

0

Si je comprends bien ...

Peut-être que vous pouvez créer une requête qui joint toutes les tables trois. Dans une seule requête rapide, vous obtiendrez toutes les informations ... Dans SQL, il pourrait être quelque chose comme:

select ... //itemColumns, tagColumns 
    from item 
    join tagItem on item.id = tagItem.itemId 
    join tag on tag.id = tagItem.tagId 
    where ... // your other conditions 
Questions connexes