帮助两个表linq查询

我想显示类别和子类别,如下所示: 第1类   子类别1   子类别2   子类别3 第2类   子类别5   子类别6   子类别7 换句话说,foreach类别,显示属于下面每个类别的子类别。 我的两张桌子是这样的: 类别- 类别ID 名称 SubCategory- SubCategoryID SubCategoryName 类别ID 我有一个从类别到子类别的外键,一个到多个。 这是我在代码中的位置,它显示了foreach类别的所有子类别。
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>";
}
    
已邀请:
如果添加一个into子句,它会将相关的类别分组到一个可以轻松迭代的集合中。 这是如何做:
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...
        }   
    }
}
    
如果您的模型中有导航属性:
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>";
如果您没有添加对模型的引用,您仍然可以使用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)}
);
    
如您所见,有许多“正确”的答案。这是我如何做到的:
// 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);
}
我已经做了各种“改进”,这在一个长期的,现实世界的项目中是有意义的。请随意忽略对您的特定情况没有意义的那些。     

要回复问题请先登录注册