C# 使用具有树结构的LINQ
我使用EF和Linq从数据库返回值。我有一个C# 使用具有树结构的LINQ,c#,linq,entity-framework,lambda,C#,Linq,Entity Framework,Lambda,我使用EF和Linq从数据库返回值。我有一个文件夹结构,文件夹可以包含文件夹列表或设备列表。我想要的是能够构建一个所有设备s的列表,这些设备位于(或位于)一个文件夹中,包括属于该文件夹的任何文件夹(假设我想要查看顶级目录中的所有文件,其中也包括子目录) 这里真正重要的是可能有很多设备,所以我需要分页,所以理想情况下这一切都可以用LINQ完成,这样我可以在返回结果集之前对查询进行排序和分页 这是我的设置的基本版本(为了简单起见,删除了键、注释和其他内容) 公共类文件夹 { 公共虚拟ICollect
文件夹
结构,文件夹可以包含文件夹
列表或设备
列表。我想要的是能够构建一个所有设备
s的列表,这些设备位于(或位于)一个文件夹中,包括属于该文件夹的任何文件夹(假设我想要查看顶级目录中的所有文件,其中也包括子目录)
这里真正重要的是可能有很多设备,所以我需要分页,所以理想情况下这一切都可以用LINQ完成,这样我可以在返回结果集之前对查询进行排序和分页
这是我的设置的基本版本(为了简单起见,删除了键、注释和其他内容)
公共类文件夹
{
公共虚拟ICollection子项{get;set;}
公共虚拟ICollection设备{get;set;}
}
//这是我目前拥有的只返回1个文件夹的函数
//需要以某种方式扩展以返回其下所有文件夹的设备
函数GetFolderDevices(int-folderId、分页选项选项)
{
//获取所有文件夹和设备
使用(var dbObj=this.context.CreateDBContext())
{
EMDB.Models.Folder Folder=dbObj
.通讯录
.Include(a=>a.Devices.Select(d=>d.Settings))
.FirstOrDefault(f=>f.FolderId==FolderId);
//在此处应用分页(已处理)
}
}
我相信您可以使用迭代器。像这样的事情可能会奏效:
static IEnumerable<Folder> Descendants(Folder root)
{
var nodes = new Stack<Folder>(new[] { root });
while (nodes.Any())
{
Folder node = nodes.Pop();
yield return node;
foreach (var n in node.Children) nodes.Push(n);
}
}
在数据库中使用公共表表达式准备视图,并将其映射到EF。不确定该怎么做?怎么做?您可以像表一样轻松地将视图映射到EF,但您必须记住,使用该映射可能无法插入/更新。我不确定的是(视图,映射它,它意味着什么?)我会为此使用递归函数-主要是因为它(在我看来)使代码更具可读性。据我所知,您可以这样做:这里唯一的问题是调试,当您遇到堆栈溢出以外的异常时。在每个深度上都没有局部变量的调用堆栈和状态。对于更简单的逻辑,它是可读的,您只是在迭代,但是当您有更多的条件要计算时,它就变得很困难了。您如何知道当前迭代的深度?尝试打印缩进等于深度的树,看看代码有多脏。我认为另一个问题是我完全没有回答眼前的问题(我写了上面的答案)。此解决方案仍将在C#类中进行排序和分页。似乎我急于写答案,而不是阅读和理解问题-对不起。@Ykok太好了,你相信我,这是一些正确的方式
static IEnumerable<Folder> Descendants(Folder root)
{
var nodes = new Stack<Folder>(new[] { root });
while (nodes.Any())
{
Folder node = nodes.Pop();
yield return node;
foreach (var n in node.Children) nodes.Push(n);
}
}
// This is the function I currently have that only returns 1 folder
// needs to somehow be expanded to return devices for all folders beneath it too
function GetFolderDevices(int folderId, PaginationOptions options)
{
// Get all folders and devices
using (var dbObj = this.context.CreateDBContext())
{
EMDB.Models.Folder folder = dbObj
.AddressBook
.Include(a => a.Devices.Select(d => d.Settings))
.FirstOrDefault(f => f.FolderId == folderId);
var result = from fold in Descendants(folder)
select fold;
// apply pagination here (already taken care of)
}
}