Ef核心负载树列表

编程入门 行业动态 更新时间:2024-10-26 20:22:35
本文介绍了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核心负载树列表

本文发布于:2023-11-14 04:56:04,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1586279.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:负载   核心   列表   Ef

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!