协助 LINQ 查询跨越具有不同关系的多个表

Assistance with LINQ query spanning multiple tables with different relationships

我有以下问题需要解决,并希望获得一些帮助以取得最佳进展。

我附上了一张图片,显示了 4 table 的设置(EF 已经删除了一些多对多关系的链接 table)。

我试图通过 LINQ 查询获取的内容的简要概述: (我尝试使用方法语法)。系统将允许用户在类别下提交 post(取决于他们是否可以访问该类别)以供审核,然后才会显示。这些类别有一个顶级父主题,因此是自引用的 table(但将来可能会扩展很多子主题)。每个 post 可以属于 1 个或多个类别,即 post 可以是 sportsIT(愚蠢的例子,我知道)。每个类别可以有一个或多个批准人。 announcement_approver table 将记录并成为基于流程的 table,其中一个或多个批准人必须记录 post 是否已被编辑、拒绝批准或批准被他们。这将在 announcement_posts table 中设置一个标志(因此是一对多)。

我需要获得的是所有 announcement_posts 尚未被 approved/pending(状态为假)的列表,由特定批准人的父 > 子关系分解(在哪里子句将基于 categories_approvers table 中的用户名字段)。希望我在这里解释得当。

我尝试了一种从category table开始的方法,使用.include作为类别的虚拟ICollections(自引用),cat_approvers & announcements_posts。然后我尝试加入 announcements_postsannouncements_approvers

我没能正常工作。我确实考虑过从 posts table 向后工作并包括猫 table 和 announcements_approvers,但我认为将 Category 加入 Category 和然后是审批人。

抱歉,如果我在这里有点胡扯。

Db Schema Desired Output hierarchy

Many to Many Category to Posts

编辑:

我尝试着手编写一些代码,但没有得到任何乐趣。这不包括任何 where 子句,因此它基本上包含所有类别及其子项、post、批准者和 approval_posts。我觉得我陷入了困境,需要重新开始:)

List<Category> res = db.Categories
    .Include(a => a.ChildrenCategories)
    .Include(a => a.Categories_approvers)
    .Include(a => a.Announcement_posts)
    .Include(a => a.Announcement_posts.Select(a1 => a1.Announcement_approvals).ToList())
    .ToList();

因为你没有 link table 的 many-to-many 外键,所以很难写。如果你有可能改变数据模型,你真的应该去做(这个模型很糟糕)。你应该引入一个“Announcement_Categories”或“Category_Announcements”table,它只有两个指向类别和公告的外键,那么这段代码应该可以工作:

var approveposts = 
    db.Announcement_Categories
        .Where(a => a.Announcement.Announcement_Approvers.Any() == false)
        .GroupBy(a => a.Category);

foreach (var categorygroup in approveposts)
{
    var category = categorygroup.Key;
    var posts = categorygroup.ToList();

    // Find parents
    var parents = new List<Category>();
    var parentcategory = category.Parent;
    while (parentcategory != null)
    {
        parents.Insert(0, parentcategory);
        parentcategory = parentcategory.Parent;
    }
    
    // Show data
    
}

如果你没有这个选项,你应该制作模型来存储你加载的所有信息

    db.Announcements.Where(a => a.Announcement_Approvers.Any() == false)

项。如果您不知道该怎么做,请告诉我。

编辑:

添加了初始化:

var categorygroups = new List<KeyValuePair<Category, List<Announcement>>>();

var approveposts = db.Announcements
    .Where(a => a.Announcement_Approvers.Any() == false)
    .ToList();

foreach (var post in approveposts)
{
    foreach (var category in post.Categories)
    {
        var categorygroup = categorygroups.FirstOrDefault(a => a.Key.Id == category.Id);
        if (categorygroup == null)
        {
            categorygroup = new KeyValuePair<Category, List<Announcement>>(category, new List<Announcement>());
            categorygroups.Add(categorygroup);
        }
        categorygroup.Value.Add(post);
    }
}
        
foreach (var categorygroup in categorygroups)
{
    var category = categorygroup.Key;
    var posts = categorygroup.Value;

    // Find parents
    var parents = new List<Category>();
    var parentcategory = category.Parent;
    while (parentcategory != null)
    {
        parents.Insert(0, parentcategory);
        parentcategory = parentcategory.Parent;
    }
    
    // Show data
    
}

感谢 ikwillem 的帮助,但我采用了不同的方法并坚持直接使用 entity framework & linq。

对于任何对我的解决方案感兴趣的人,请看这里。我遵循了 EF 包含方法,并使用嵌套选择进行了一些试验和错误,得到了我需要的信息。然后我简单地投影到一个新的 Vm 中。为了简单起见,我删除了一些 where 子句。

var currentUser = Authentication.GetGlobalUserName();

  db.Configuration.LazyLoadingEnabled = false;

                //this is working from posts back to categories.
                var approveposts = db.Announcement_posts
                    .Include(a => a.Categories)
                    .Include(a => a.Categories.Select(b => b.ParentCategory))
                    .Include(a => a.Categories.Select(c => c.Categories_approvers))
                    .Include(a => a.Announcement_approvals)
                    .Where(a => a.Announcement_approvals
                          .Any(b => b.approver == currentUser && a.approved == false)              
                    .Select(p => new PendingPostsVm
                    {
                        PostGuid = p.postGUID,
                        Topic = p.Categories.Select(cat => cat.name).FirstOrDefault(),
                        Theme = p.Categories.Select(cat => cat.ParentCategory.name).FirstOrDefault(),
                        PostTitle = p.title,
                        Catid = p.Categories.Select(cat => cat.id).FirstOrDefault(),
                        DateSubmitted = p.date_created
                    })
                    .OrderBy(s => s.DateSubmitted)
                    .ToList();