本文介绍了Ef核心负载树列表的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!
问题描述
根据我的模型,我想一次将数据提取为树形列表。
In accordance with my model, I want to extract the data as a tree list at once.
public class FolderInResearch : EntityBase { public FolderInResearch() { SubFolders = new List<FolderInResearch>(); } public string Name { get; set; } public Guid? ParentFolderId { get; set; } [ForeignKey("ParentFolderId")] public ICollection<FolderInResearch> SubFolders { get; set; } }推荐答案
这是配置方法并在 EF Core 中使用树结构:
This is how to configure and use the tree structure in EF Core:
实体类:
public class Folder { public Guid Id { get; set; } public string Name { get; set; } public Folder Parent { get; set; } public Guid? ParentId { get; set; } public ICollection<Folder> SubFolders { get; } = new List<Folder>(); }数据库架构配置:
protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity<Folder>(entity => { entity.HasKey(x => x.Id); entity.Property(x => x.Name); entity.HasOne(x => x.Parent) .WithMany(x => x.SubFolders) .HasForeignKey(x => x.ParentId) .IsRequired(false) .OnDelete(DeleteBehavior.Restrict); }); // ... }这是从中加载数据的方法DB作为树:
This is how to load data from DB as a tree:
{ List<Folder> all = _dbContext.Folders.Include(x => x.Parent).ToList(); TreeExtensions.ITree<Folder> virtualRootNode = all.ToTree((parent, child) => child.ParentId == parent.Id); List<TreeExtensions.ITree<Folder>> rootLevelFoldersWithSubTree = virtualRootNode.Children.ToList(); List<TreeExtensions.ITree<Folder>> flattenedListOfFolderNodes = virtualRootNode.Children.Flatten(node => node.Children).ToList(); // Each Folder entity can be retrieved via node.Data property: TreeExtensions.ITree<Folder> folderNode = flattenedListOfFolderNodes.First(node => node.Data.Name == "MyFolder"); Folder folder = folderNode.Data; int level = folderNode.Level; bool isLeaf = folderNode.IsLeaf; bool isRoot = folderNode.IsRoot; ICollection<TreeExtensions.ITree<Folder>> children = folderNode.Children; TreeExtensions.ITree<Folder> parent = folderNode.Parent; List<Folder> parents = GetParents(folderNode); }从树中获取所有父节点的示例方法:
Sample method to get all parents from the tree for node:
private static List<T> GetParents<T>(TreeExtensions.ITree<T> node, List<T> parentNodes = null) where T : class { while (true) { parentNodes ??= new List<T>(); if (node?.Parent?.Data == null) return parentNodes; parentNodes.Add(node.Parent.Data); node = node.Parent; } }树操作扩展方法和用于将实体包装到树节点中的帮助程序接口:
Tree operation extension methods and helper interface for wrapping entities into the tree nodes:
public static class TreeExtensions { /// <summary> Generic interface for tree node structure </summary> /// <typeparam name="T"></typeparam> public interface ITree<T> { T Data { get; } ITree<T> Parent { get; } ICollection<ITree<T>> Children { get; } bool IsRoot { get; } bool IsLeaf { get; } int Level { get; } } /// <summary> Flatten tree to plain list of nodes </summary> public static IEnumerable<TNode> Flatten<TNode>(this IEnumerable<TNode> nodes, Func<TNode, IEnumerable<TNode>> childrenSelector) { if (nodes == null) throw new ArgumentNullException(nameof(nodes)); return nodes.SelectMany(c => childrenSelector(c).Flatten(childrenSelector)).Concat(nodes); } /// <summary> Converts given list to tree. </summary> /// <typeparam name="T">Custom data type to associate with tree node.</typeparam> /// <param name="items">The collection items.</param> /// <param name="parentSelector">Expression to select parent.</param> public static ITree<T> ToTree<T>(this IList<T> items, Func<T, T, bool> parentSelector) { if (items == null) throw new ArgumentNullException(nameof(items)); var lookup = items.ToLookup(item => items.FirstOrDefault(parent => parentSelector(parent, item)), child => child); return Tree<T>.FromLookup(lookup); } /// <summary> Internal implementation of <see cref="ITree{T}" /></summary> /// <typeparam name="T">Custom data type to associate with tree node.</typeparam> internal class Tree<T> : ITree<T> { public T Data { get; } public ITree<T> Parent { get; private set; } public ICollection<ITree<T>> Children { get; } public bool IsRoot => Parent == null; public bool IsLeaf => Children.Count == 0; public int Level => IsRoot ? 0 : Parent.Level + 1; private Tree(T data) { Children = new LinkedList<ITree<T>>(); Data = data; } public static Tree<T> FromLookup(ILookup<T, T> lookup) { var rootData = lookup.Count == 1 ? lookup.First().Key : default(T); var root = new Tree<T>(rootData); root.LoadChildren(lookup); return root; } private void LoadChildren(ILookup<T, T> lookup) { foreach (var data in lookup[Data]) { var child = new Tree<T>(data) {Parent = this}; Children.Add(child); child.LoadChildren(lookup); } } } }更多推荐
Ef核心负载树列表
发布评论