سؤال

أريد أن أعرض الفئات والفئات الفرعية مثل:

الفئة 1
الفئة الفرعية 1
الفئة الفرعية 2
الفئة الفرعية 3

الفئة 2
الفئة الفرعية 5
الفئة الفرعية 6
الفئة الفرعية 7

بمعنى آخر ، فئة Foreach ، تعرض الفئات الفرعية التي تنتمي إلى كل واحدة تحتها.

طاولاتي مثل هكذا:
فئة-
معرف الفئة
اسم

تصنيف فرعي-
الفئة الفرعية
الاسم الفرعي
معرف الفئة
لدي مفتاح خارجي من الفئة إلى الفئة الفرعية واحدة إلى كثيرين.

هنا حيث حصلت على الكود ، والتي تعرض جميع الفئات الفرعية 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>";
}
هل كانت مفيدة؟

المحلول

إذا قمت بإضافة جملة إلى جملة ، فستقوم بتجميع الفئات ذات الصلة في مجموعة يمكنك تكرارها بسهولة.

إليك الطريقة:

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

لقد قمت بإجراء "تحسينات" مختلفة من شأنها أن تكون منطقية في مشروع العالم الحقيقي على المدى الطويل. لا تتردد في تجاهل تلك التي لا معنى لها لموقفك الخاص.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top