Domanda

Voglio categorie di visualizzazione e sottocategorie in questo modo:

Categoria 1
  Sotto 1
  Sotto 2
  Sotto 3
Categoria 2
  Sotto 5
  Sotto 6
  Sotto 7

In altre parole, categoria foreach, visualizzare le sottocategorie che appartengono ad ognuno di sotto.

I miei due tabelle sono in questo modo:
categoria-
IDCategoria
Nome

SubCategory-
SubCategoryID
SubCategoryName
IDCategoria
Ho una chiave esterna da categoria a sottocategoria un uno a molti.

Ecco dove ho ottenuto il codice, che visualizza tutte le sottocategorie foreach categoria.

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>";
}
È stato utile?

Soluzione

Se si aggiunge una clausola INTO che raggrupperà le relative categorie in una collezione che si può facilmente iterare sopra.

Ecco come:

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...
        }   
    }
}

Altri suggerimenti

Se si dispone di proprietà di navigazione nel modello:

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>";

Se non avete aggiunto i riferimenti al modello è ancora possibile ottenere quello che ti serve utilizzando 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)}
);

Come si può vedere, ci sono un certo numero di risposte "giuste". Ecco come lo farei:

// 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);
}

Ho fatto diversi "miglioramenti" che avrebbe senso in una prospettiva a lungo termine, progetto del mondo reale. Sentitevi liberi di ignorare quelli che non hanno senso per la vostra situazione particolare.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top