2010-11-29 4 views
3

Je veux afficher les catégories et sous-catégories comme ceci:aide avec un LINQ deux tables requête

Catégorie 1
Sous-catégorie 1
Sous-catégorie 2
Sous-catégorie 3

Catégorie 2
Sous-catégorie 5
Sous-catégorie 6
Sous-catégorie 7

En d'autres termes, pour chaque catégorie, affichez les sous-catégories qui appartiennent à chacun d'eux.

Mes deux tableaux sont comme ceci:
catégorie-
CategoryID
Nom

SubCategory-
SubCategoryID
SubCategoryName
CategoryID
J'ai une clé étrangère de la catégorie à la sous-catégorie un trop.

Voici où je suis dans le code, qui affiche toutes les sous-catégories pour chaque catégorie.

public void displayLinqCategory() 
{ 
    MyDataContext dbm = new MyDataContext(); 

    var q = from category in dbm.Categories 
      join subCat in dbm.SubCategories 
      on category.CategoryID equals subCat.CategoryID 
      select new { category.Name, subCat.SubCategoryName }; 

    resultSpan.InnerHtml += "<table>"; 
    foreach (var c in q) 
    { 
     resultSpan.InnerHtml += "<tr><td>" + c.Name + "</td></tr>"; 
     foreach (var s in q) 
     { 
      resultSpan.InnerHtml += "<tr><td>&nbsp;&nbsp;&nbsp;" + s.SubCategoryName + "</td></td>"; 
     } 

    } 
    resultSpan.InnerHtml += "</table>"; 
} 

Répondre

0

Si Si vous ajoutez une clause into, les catégories associées seront regroupées dans une collection que vous pourrez facilement parcourir.

Voilà comment:

using (var dbm = new MyDataContext()) 
{ 
    var query = dbm.Categories 
       join s in dbm.SubCategories on c.CategoryID equals s.CategoryID 
       //group the related subcategories into a collection 
       into subCollection 
       select new { Category = c, SubCategories = subCollection }; 

    foreach (var result in query) 
    { 
     //use result.Category here... 

     //now go through the subcategories for this category 
     foreach (var sub in result.Subcategories) 
     { 
      //use sub here... 
     } 
    } 
} 
+0

Merci, cela fonctionne très bien. Est-il vraiment nécessaire d'utiliser des instructions? Je pensais que le CLR prenait soin de disposer des données inutilisées en mémoire. –

+0

Cochez cette question pour avoir un bon aperçu de la disposition de Linq à SQL DataContexts de Jon Skeet; http://stackoverflow.com/questions/389822/when-should-i-dispose-of-a-data-context. Sa réponse ne couvre que Linq to SQL, la disposition pourrait être plus importante pour d'autres fournisseurs de Linq ... –

0

Si vous avez des propriétés de navigation dans votre modèle:

MyDataContext dbm = new MyDataContext(); 

var groups = dbm.SubCategories 
      .Select(x=> new { CatName = x.Category.Name, x.SubCategoryName }); 
      .GroupBy(x=>x.CatName); 

resultSpan.InnerHtml += "<table>"; 
foreach (var group in groups) 
{ 
    resultSpan.InnerHtml += "<tr><td>" + group.Key + "</td></tr>"; 
    foreach (var s in group) 
    { 
     resultSpan.InnerHtml += "<tr><td>&nbsp;&nbsp;&nbsp;" + s.SubCategoryName + "</td></td>"; 
    } 

} 
resultSpan.InnerHtml += "</table>"; 

si vous n'avez pas ajouté des références à votre modèle, vous pouvez toujours obtenir ce que vous avez besoin en utilisant GroupJoin

var groups = dbm.Categories 
    .GroupJoin(
     dbm.SubCategories, 
     x => x.CategoryID, 
     x => x.CategoryID, 
     (x, y) => new {Category = x.CategoryName, SubCategories = y.Select(s=>s.SubCategoryName)} 
); 
0

Comme vous pouvez le voir, il y a un certain nombre de réponses « droit ». Voici comment je le ferais:

// Data access belongs in its own area. Don't do it alongside HTML generation. 
// Program to an interface so you can mock this repository in unit tests. 
public interface ICategoryInfoRepository { 
    IEnumerable<CategoryInfo> GetCategoryInfo(); 
} 

public class CategoryInfo { 
    public string CategoryName {get;set;} 
    public IEnumerable<string> SubCategoryNames {get;set;} 
} 

public class CategoryInfoRepository : ICategoryInfoRepository 
{ 
    public IEnumerable<CategoryInfo> GetCategoryInfo() 
    { 
     // The 'using' clause ensures that your context will be disposed 
     // in a timely manner. 
     using (var dbm = new MyDataContext()) 
     { 
      // This query makes it pretty clear what you're selecting. 
      // The groupings are implied. 
      var q = from category in dbm.Categories 
        select new { 
         CategoryName = category.Name, 
         SubCategoryNames = 
          from subcategory in category.SubCategories 
          select subcategory.Name 
        }; 
      // Make sure all the data is in memory before disposing the context 
      return q.ToList(); 
     } 
    } 
} 
// Since all this method does is convert its input into a string, it would 
// be very easy to unit-test. 
public string GetCategoriesHtml(IEnumerable<CategoryInfo> categoryInfos) { 
    // A StringBuilder will make this HTML generation go much faster 
    var sb = new StringBuilder(); 
    // Don't use tables to represent non-tabular data. 
    // This is a list, so let's make it a list. 
    // Use CSS to format it to your liking. 
    sb.Append("<ul>"); 
    foreach(var categoryInfo in categoryInfos) 
    { 
     sb.Append("<li>").Append(categoryInfo.CategoryName).Append("<ul>"); 
     foreach(var subCategoryName in categoryInfo.SubCategoryNames) 
     { 
      sb.Append("<li>").Append(subCategoryName).Append("</li>"); 
     } 
     sb.Append("</ul></li>"); 
    } 
    sb.Append("</ul>"); 
    return sb.ToString(); 
} 

public void DisplayLinqCategory() 
{ 
    // The repository would ideally be provided via dependency injection. 
    var categoryInfos = _categoryInfoRepository.GetCategoryInfo(); 
    resultSpan.InnerHtml = GetCategoriesHtml(categoryInfos); 
} 

J'ai fait diverses « améliorations » qui ont un sens dans un long terme, projet dans le monde réel. N'hésitez pas à ignorer ceux qui n'ont pas de sens pour votre situation particulière.