协助 LINQ 查询跨越具有不同关系的多个表
Assistance with LINQ query spanning multiple tables with different relationships
我有以下问题需要解决,并希望获得一些帮助以取得最佳进展。
我附上了一张图片,显示了 4 table 的设置(EF 已经删除了一些多对多关系的链接 table)。
我试图通过 LINQ
查询获取的内容的简要概述:
(我尝试使用方法语法)。系统将允许用户在类别下提交 post(取决于他们是否可以访问该类别)以供审核,然后才会显示。这些类别有一个顶级父主题,因此是自引用的 table(但将来可能会扩展很多子主题)。每个 post 可以属于 1 个或多个类别,即 post 可以是 sports
和 IT
(愚蠢的例子,我知道)。每个类别可以有一个或多个批准人。 announcement_approver
table 将记录并成为基于流程的 table,其中一个或多个批准人必须记录 post 是否已被编辑、拒绝批准或批准被他们。这将在 announcement_posts
table 中设置一个标志(因此是一对多)。
我需要获得的是所有 announcement_posts
尚未被 approved/pending(状态为假)的列表,由特定批准人的父 > 子关系分解(在哪里子句将基于 categories_approvers
table 中的用户名字段)。希望我在这里解释得当。
我尝试了一种从category
table开始的方法,使用.include作为类别的虚拟ICollections
(自引用),cat_approvers
& announcements_posts
。然后我尝试加入 announcements_posts
到 announcements_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();
我有以下问题需要解决,并希望获得一些帮助以取得最佳进展。
我附上了一张图片,显示了 4 table 的设置(EF 已经删除了一些多对多关系的链接 table)。
我试图通过 LINQ
查询获取的内容的简要概述:
(我尝试使用方法语法)。系统将允许用户在类别下提交 post(取决于他们是否可以访问该类别)以供审核,然后才会显示。这些类别有一个顶级父主题,因此是自引用的 table(但将来可能会扩展很多子主题)。每个 post 可以属于 1 个或多个类别,即 post 可以是 sports
和 IT
(愚蠢的例子,我知道)。每个类别可以有一个或多个批准人。 announcement_approver
table 将记录并成为基于流程的 table,其中一个或多个批准人必须记录 post 是否已被编辑、拒绝批准或批准被他们。这将在 announcement_posts
table 中设置一个标志(因此是一对多)。
我需要获得的是所有 announcement_posts
尚未被 approved/pending(状态为假)的列表,由特定批准人的父 > 子关系分解(在哪里子句将基于 categories_approvers
table 中的用户名字段)。希望我在这里解释得当。
我尝试了一种从category
table开始的方法,使用.include作为类别的虚拟ICollections
(自引用),cat_approvers
& announcements_posts
。然后我尝试加入 announcements_posts
到 announcements_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();