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

时间:2019-07-12 08:51:10

标签: c# entity-framework linq model-view-controller entity-framework-6

我有以下问题要解决,希望以最佳的方式获得帮助。

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

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

我需要获取的是所有announcement_posts的列表,这些列表未被批准/待审批(状态为false),并由特定批准者的Parent> Child关系分解(where子句将基于(在categories_approvers表的用户名字段中)。希望我已经在这里正确解释了。

我尝试了一种从category表开始的方法,将.include用于类别(自引用),ICollectionscat_approvers的虚拟announcements_posts 。然后,我尝试将announcements_posts加入announcements_approvers

我无法正常工作。我确实考虑过从posts表向后工作,并包括cat表和announces_approvers,但我认为将Category依次加入Category和然后批准者是一个棘手的情况。

对不起,如果我在这里摇晃一下。

Db Schema Desired Output hierarchy

Many to Many Category to Posts

编辑:

我尝试从某些代码开始,但没有获得喜悦。这不包括任何where子句,因此其基本上是所有类别及其子项,职位,批准者和rovaling_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();

2 个答案:

答案 0 :(得分:0)

因为没有用于多对多外键的链接表,所以这很难编写。如果您有可能更改数据模型,则应该确实这样做(此模型很糟糕)。您应该引入一个“ Announcement_Categories”或“ Category_Announcements”表,该表只有两个用于类别和公告的外键,然后此代码才能工作:

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

}

答案 1 :(得分:0)

感谢ikwillem的协助,但我寻求另一种方法,并坚持使用实体框架和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();