Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/ruby/21.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# Ef核心负载树列表_C#_Asp.net_Asp.net Core_Entity Framework Core_Treelist - Fatal编程技术网

C# Ef核心负载树列表

C# Ef核心负载树列表,c#,asp.net,asp.net-core,entity-framework-core,treelist,C#,Asp.net,Asp.net Core,Entity Framework Core,Treelist,根据我的模型,我希望立即将数据提取为树列表 public class FolderInResearch : EntityBase { public FolderInResearch() { SubFolders = new List<FolderInResearch>(); } public string Name { get; set; } public Guid? ParentFolderId { get; se

根据我的模型,我希望立即将数据提取为树列表

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; }        
}
公共类FolderInSearch:EntityBase
{
公共民俗学研究()
{
子文件夹=新列表();
}
公共字符串名称{get;set;}
公共Guid?ParentFolderId{get;set;}
[ForeignKey(“ParentFolderId”)]
公共ICollection子文件夹{get;set;}
}

这是如何配置和使用
EF核心中的树结构的:

实体类:

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>();
}
公共类文件夹
{
公共Guid Id{get;set;}
公共字符串名称{get;set;}
公用文件夹父项{get;set;}
公共Guid?父ID{get;set;}
公共ICollection子文件夹{get;}=new List();
}
数据库架构配置:

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);
    });

    // ...
}
模型创建时受保护的覆盖无效(ModelBuilder ModelBuilder)
{
modelBuilder.Entity(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(假)
.OnDelete(DeleteBehavior.Restrict);
});
// ...
}
以下是如何以树的形式从数据库加载数据:

{
    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);
}
{
列出所有=_dbContext.Folders.Include(x=>x.Parent.ToList();
TreeExtensions.ITree virtualRootNode=all.ToTree((父,子)=>child.ParentId==parent.Id);
List rootLevelFoldersWithSubTree=virtualRootNode.Children.ToList();
List flattedListofFolderNodes=virtualRootNode.Children.flatte(node=>node.Children.ToList();
//可以通过节点检索每个文件夹实体。数据属性:
TreeExtensions.ITree folderNode=flattedListofFolderNodes.First(node=>node.Data.Name==“MyFolder”);
Folder Folder=folderNode.Data;
int-level=folderNode.level;
bool isLeaf=folderNode.isLeaf;
bool isRoot=folderNode.isRoot;
ICollection children=folderNode.children;
TreeExtensions.ITree parent=folderNode.parent;
List parents=GetParents(folderNode);
}
从节点的树中获取所有父节点的示例方法:

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;
    }
}
private static List GetParents(TreeExtensions.ITree节点,List parentNodes=null),其中T:class
{
while(true)
{
parentNodes???=新列表();
如果(node?.Parent?.Data==null)返回parentNodes;
添加(node.Parent.Data);
node=node.Parent;
}
}
用于将实体包装到树节点的树操作扩展方法和辅助接口:

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);
            }
        }
    }
}
公共静态类树扩展
{
///树节点结构的通用接口
/// 
公共接口ITree
{
T数据{get;}
ITree父项{get;}
ICollection子项{get;}
bool IsRoot{get;}
布尔岛{get;}
int级别{get;}
}
///将树展平为节点的普通列表
公共静态IEnumerable展平(此IEnumerable节点,Func childrenSelector)
{
如果(nodes==null)抛出新的ArgumentNullException(nameof(nodes));
返回nodes.SelectMany(c=>childrenSelector(c).Flatten(childrenSelector)).Concat(nodes);
}
///将给定列表转换为树。
///要与树节点关联的自定义数据类型。
///收集物品。
///表达式以选择父级。
公共静态ITree目录树(此IList项,Func parentSelector)
{
如果(items==null)抛出新的ArgumentNullException(nameof(items));
var lookup=items.ToLookup(item=>items.FirstOrDefault(parent=>parentSelector(parent,item)),
child=>child);
返回Tree.FromLookup(查找);
}
///内部执行
///要与树节点关联的自定义数据类型。
内部类树:ITree
{
公共T数据{get;}
公共ITree父项{get;private set;}
公共ICollection子项{get;}
公共bool IsRoot=>Parent==null;
public bool IsLeaf=>Children.Count==0;
public int Level=>IsRoot?0:Parent.Level+1;
私有树(T数据)
{
Children=newlinkedlist();
数据=数据;
}
公共静态树FromLookup(ILookup查找)
{
var rootData=lookup.Count==1?lookup.First();
var root=新树(rootData);
root.LoadChildren(查找);
返回根;
}
私有void LoadChildren(ILookup查找)
{
foreach(查找[data]中的var数据)
{
var child=新树(数据){Parent=this};
添加(child);
LoadChildren(查找);
}
}
}
}

查看这篇关于使用EF递归加载的文章。我读了这篇文章,但有点困惑。我无法完全理解。使用以下技巧加载整棵树相当容易。递归加载只是树的一部分是。。。你可以参考:我已经决定根据我的答案写一篇博文