将LINQ与树结构结合使用
本文关键字:结合 结构 LINQ | 更新日期: 2023-09-27 18:28:06
我使用EF和Linq从数据库返回值。我有一个Folder
结构,文件夹可以包含Folder
的列表或Device
的列表。我想要的是能够构建一个位于文件夹内(或文件夹下)的所有Device
的列表,包括属于该文件夹的任何文件夹(想象一下,我想查看顶层目录中的所有文件,该目录也包括子目录)。
这里真正的关键是可能有很多设备,所以我想要分页,所以理想情况下,这一切都可以用LINQ完成,这样我就可以在返回结果集之前对查询进行排序和分页。
这是我的设置的基本版本(为了简单起见,删除了密钥、注释和其他内容)
public class Folder
{
public virtual ICollection<Folder> Children { get; set; }
public virtual ICollection<Device> Devices { get; set; }
}
// 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);
// apply pagination here (already taken care of)
}
}
我相信您可以使用迭代器。像这样的东西可能会起作用:
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)
}
}