在 EF Core 中实现递归属性加载

     2023-03-30     287

关键词:

【中文标题】在 EF Core 中实现递归属性加载【英文标题】:Implementing recursive property loading in EF Core 【发布时间】:2016-12-06 03:32:08 【问题描述】:

我使用的是 .NET Core 1.1.0、EF Core 1.1.0、VS 2015。

我正在为帖子/cmets 编写一个系统,我需要一个函数来加载评论及其所有子项及其相关属性。这是我的课程的简化版本:

public class Comment

    public long Id  get; set; 

    public string Content  get; set; 

    public User User  get; set; 

    public ICollection<Comment> Replies  get; set; 


public class User

    public long Id  get; set; 

    public string Name  get; set; 

    public Avatar Avatar  get; set; 


public class Avatar

    public string Url  get; set; 

任何给定的评论都可以有任意数量的回复:

-PARENT
    -CHILD 1
    -CHILD 2
        -CHILD 3
    -CHILD 4
    -CHILD 5
        -CHILD 6
            -CHILD 7

因此,给定父评论的 ID,我需要加载整个树,包括用户及其各自的头像。 (我在其他地方进行了控制,以确保这些树不会变得笨拙,此时我并不担心可能会获取太多数据。)

EF Core 文档中的Loading Related Data 页面非常有用,但我不确定如何最好地处理这个问题。我已经尝试将一些东西放在一起,但我无法概念化如何将它们组合在一起。再次注意:我使用的是 EF Core 1.1.0,因此我可以访问“显式加载”部分中的函数。

如何在给定父评论 ID 的情况下加载整个 cmets 树?

【问题讨论】:

每个孩子到数据库的往返行程可能非常重要。使用 SQL 进行递归 CTE 并让 EF 映射结果可能会更好。 @ESG 我以前从未听说过 CTE,在阅读了它们之后,它看起来可能是完美的。我再仔细看看,谢谢! 【参考方案1】:

我没有数据库,所以我只是在内存中完成了它,但如果你关注我的 cmets,它会为你工作。注意我在内存中的对象,只有 id 为 2 的评论有回复。

LoadComment 方法是一切发生的地方。剩下的只是我需要的设置代码。

class Program

    static void Main(string[] args)
    
        var result = LoadComment(1, null);
        Console.ReadKey();

    



public static Comment LoadComment(long id, Comment com) 

   Comment res = new Comment();
   if( com == null ) 
   
      // You would call your context here and write db.Single(x => x.Id == id).Include(x => x.User.Avatar);
      var first = db.Single( x => x.Id == id );

      res = new Comment  Id = first.Id, Replies = first.Replies.ToList(), User = first.User ;
      foreach( var item in first.Replies ) 
      
         LoadComment( item.Id, item );
      
   
   else 
   
      // You would call your context here and write db.Single(x => x.Id == id).Include(x => x.User.Avatar);
      var child = db.SingleOrDefault( x => x.Id == id );
      if( child == null ) 
      
         return null;
      
      com.Replies = new List<Comment>();
      com.Replies.Add( new Comment  Id = child.Id, Replies = child.Replies.ToList(), User = child.User  );
      foreach( var item in child.Replies ) 
      
         LoadComment( item.Id, com );
      
   


   return res;


    private static Comment cm1 = new Comment
    
        Id = 1,
        User = new User  Id = 1, Avatar = new Avatar  Url = "1"  ,
        Replies = new List<Comment> 
        new Comment  Id = 2 ,
        new Comment  Id = 3 ,
        new Comment  Id = 4 ,
        new Comment  Id = 5  ,
        Content = "ContentForCommentId1"
    ;

    private static Comment cm2 = new Comment
    
        Id = 2,
        User = new User  Id = 2, Avatar = new Avatar  Url = "2"  ,
        Replies = new List<Comment> 
        new Comment  Id = 22 ,
        new Comment  Id = 33 ,
        new Comment  Id = 44 ,
        new Comment  Id = 55  ,
        Content = "ContentForCommentId2"
    ;
    private static List<Comment> db = new List<Comment>  cm1, cm2 ;


【讨论】:

这看起来很有希望!我在最后一个 foreach: Collection was modified; enumeration operation may not execute. 收到了这个错误,它发生在加载第一个评论的孩子之后; foreach 中的第二项触发异常。 抱歉,if 和 else 块中有一个小错误。请使用LoadComment 方法中的新代码重试。如果它不起作用,那么我将不得不创建一个数据库并尝试以这种方式对其进行测试。 我最终使用了这种方法,只是稍微调整了一下。您提供的更新代码完美运行,我只是为我的代码库更改了几处。非常感谢!【参考方案2】:

我就是这样解决的。与 Yoshi 的非常相似,但可能对某人有所帮助。

private async Task<Comment> GetComment(Guid id, CancellationToken cancellationToken)

    var wm = await _context.Comments
                           .Include(x => x.Replies)
                           .SingleOrDefaultAsync(x => x.Id == id, cancellationToken);

    for (var i = 0; i < wm.Replies.Count; i++)
    
        if (!wm.Replies[i].IsDeleted)
            wm.Replies[i] = await GetComment(wm.Replies[i].Id, cancellationToken);
    

    return wm;

【讨论】:

【参考方案3】:

为什么不使用 Eagerly Loading? 急切地加载多个级别 我在 .NETCore (VS2015) 的项目中使用过它

也可以急切地加载多个级别的相关实体。下面的查询显示了如何对集合和参考导航属性执行此操作的示例。

using (var context = new BloggingContext()) 
 
    // Load all blogs, all related posts, and all related comments 
    var blogs1 = context.Blogs 
                       .Include(b => b.Posts.Select(p => p.Comments)) 
                       .ToList(); 

    // Load all users their related profiles, and related avatar 
    var users1 = context.Users 
                        .Include(u => u.Profile.Avatar) 
                        .ToList(); 

    // Load all blogs, all related posts, and all related comments  
    // using a string to specify the relationships 
    var blogs2 = context.Blogs 
                       .Include("Posts.Comments") 
                       .ToList(); 

    // Load all users their related profiles, and related avatar  
    // using a string to specify the relationships 
    var users2 = context.Users 
                        .Include("Profile.Avatar") 
                        .ToList(); 

请注意,目前无法过滤加载了哪些相关实体。包含将始终引入所有相关实体。

这是我的参考:"Microsoft.EntityFrameworkCore.SqlServer": "1.1.0-preview2-22683"

希望对你有帮助。

【讨论】:

据我了解,我必须为我想要引入的每一层链接.Include().ThenInclude(),这是不可行的,因为事先不知道 cmets 的深度。这不正确吗? 嗯..你是对的。你当然应该知道孩子和孙子。对于多层,.ThenInclude() 也可能存在一些问题。见:***.com/questions/40953665/…

如何在 .NET Core 中实现处理自定义属性的 Swashbuckle IOperationFilter

】如何在.NETCore中实现处理自定义属性的SwashbuckleIOperationFilter【英文标题】:HowtoimplementaSwashbuckleIOperationFilterthatprocessescustomattributesin.NETCore【发布时间】:2020-03-0108:28:16【问题描述】:我已经实现了Swashbuckle.Swagger.IOperationFilter来... 查看详情

在 ASP.NET Core WebAPI 中实现 JSON 合并补丁

】在ASP.NETCoreWebAPI中实现JSON合并补丁【英文标题】:ImplementingJSONMergePatchinASP.NETCoreWebAPI【发布时间】:2018-02-2221:42:09【问题描述】:我有兴趣在我的ASP.NETCoreWebAPI中添加对部分更新的支持,我只更新调用者提供的资源的属性,而... 查看详情

EF Core 6.0 导航属性未加载

】EFCore6.0导航属性未加载【英文标题】:EFCore6.0navigationpropertynotloading【发布时间】:2022-01-0411:16:53【问题描述】:我正在尝试构建一个简单的基于ASP.NETCore6的WebAPI。我从遵循Microsoft的最小WebAPI教程https://docs.microsoft.com/en-us/aspnet/c... 查看详情

在 .Net Core 中实现刷新令牌功能的最佳位置?

】在.NetCore中实现刷新令牌功能的最佳位置?【英文标题】:BestplacetoimplementRefreshtokenfunctionalityin.NetCore?【发布时间】:2021-09-2308:32:45【问题描述】:我们希望使用身份服务器中的刷新令牌生成新的访问令牌。我们希望实现与SPA... 查看详情

如何在 EF Core 中使用 DbFunction 翻译?

...述】:我正在寻找类似@​​987654324@的东西,它在SQLServer中实现,但使用MySQL的MATCH...AGAINST语法。这是我目前的工作流程:AspNetCore2.1.1EntityFrameworkCore2.1.4P 查看详情

如何在 Apache Spark 中实现递归算法?

】如何在ApacheSpark中实现递归算法?【英文标题】:HowtoimplementrecursivealgorithmsinApacheSpark?【发布时间】:2021-09-0706:10:17【问题描述】:我有一个问题,我想在Spark中实现递归算法,并查看是否有任何建议可以在Spark中构建它,或者... 查看详情

如何在Castle.Core中实现IProxyGenerationHook的类中实现Equals和GetHashCode的覆盖方法?

】如何在Castle.Core中实现IProxyGenerationHook的类中实现Equals和GetHashCode的覆盖方法?【英文标题】:HowtoimplementtheoverridemethodsofEqualsandGetHashCodeinaclassthatimplementsIProxyGenerationHookinCastle.Core?【发布时间】:2021-04-1817:06:39【问题描述】:阅... 查看详情

如何使用 spring-security-core-ldap 插件在 grails 中实现 LDAP 身份验证?

】如何使用spring-security-core-ldap插件在grails中实现LDAP身份验证?【英文标题】:HowtoimplementLDAPauthenticationingrailswithspring-security-core-ldapplugin?【发布时间】:2012-02-1909:44:11【问题描述】:我是grails的新手,正在尝试实现LDAP身份验证... 查看详情

如何在使用 TPT 层次结构时首先在 EF 代码中实现并发

】如何在使用TPT层次结构时首先在EF代码中实现并发【英文标题】:HowtoimplementConcurrencyinEFcodefirstwhileusingaTPThierarchy【发布时间】:2011-04-0809:56:55【问题描述】:大家好!我正在尝试首先使用实体​​框架代码实现乐观并发检查(... 查看详情

如何在 TensorFlow 中实现递归神经网络?

】如何在TensorFlow中实现递归神经网络?【英文标题】:HowcanIimplementarecursiveneuralnetworkinTensorFlow?【发布时间】:2016-08-3110:52:47【问题描述】:是否有某种方法可以使用TensorFlow实现类似于[Socheretal.2011]中的递归神经网络?请注意,... 查看详情

存储库模式 EF Core 更新方法

...用存储库模式和工作单元模式的问题。我目前正在控制器中实现更新功能。现在,在这一点上,我不确定更新实体的最佳方法是什么。我看过一些视频,他们说Update方法不应该出现在这样的存储 查看详情

如何在两个表之间的组中实现递归连接?

】如何在两个表之间的组中实现递归连接?【英文标题】:HowcanIimplementthisarecursivejoininagroupbetweentwotables?【发布时间】:2013-02-1814:52:27【问题描述】:我在一个名为AVAILABLE_TEMPLATES的表中有一些杂乱的数据。这是一个简单的例子:... 查看详情

获取在 .NET Core 中实现接口的所有类型

】获取在.NETCore中实现接口的所有类型【英文标题】:Gettingalltypesthatimplementaninterfacein.NETCore【发布时间】:2016-11-2110:51:18【问题描述】:使用反射,我如何获得所有在.NETCore中实现特定接口的类型?我注意到.NET4.6中可用的方法不... 查看详情

如何将领域类与EF代码第一层分离并在项目中实现DDD

】如何将领域类与EF代码第一层分离并在项目中实现DDD【英文标题】:HowtoseparatedomainclassesfromEFcodefirstlayerandimplementDDDinproject【发布时间】:2017-03-1410:29:27【问题描述】:我正在尝试首先使用EF代码来控制DDD。我看到人们首先使用E... 查看详情

使用 Swagger 在 ASP.NET Core 中实现 OAuth

】使用Swagger在ASP.NETCore中实现OAuth【英文标题】:OAuthImplementationinASP.NETCoreusingSwagger【发布时间】:2021-02-1818:02:22【问题描述】:我想在我的Web应用程序中实现OAuth,为此我在startup.cs中添加了以下代码publicstaticIServiceCollectionAddSwagg... 查看详情

如何在ef中实现leftjoin查询

多表连接查询按要查的结果而定第一个,就是普通的连接查询,等同于selectC.字段一,count(A.主键)fromTableAinnerjoinTableBonA.B的主键=B.主键innerjoinTableConB.C的主键=C.主键groupC.字段一或selectC.字段一,。参考技术A下面是一个groupby的linq查询... 查看详情

在 Swift Core Data 项目中实现 UISearchController

】在SwiftCoreData项目中实现UISearchController【英文标题】:ImplementingaUISearchControllerinSwiftCoreDataProject【发布时间】:2015-02-2213:55:45【问题描述】:我目前正在学习iOS开发课程。作为作业的一部分,我的任务是使用Swift中的CoreData在笔... 查看详情

Fluent API 首先在 EF 代码中实现零或一到零或一的关系

】FluentAPI首先在EF代码中实现零或一到零或一的关系【英文标题】:ImplementingZeroOrOnetoZeroOrOnerelationshipinEFCodefirstbyFluentAPI【发布时间】:2013-01-2000:23:56【问题描述】:我有两个POCO课程:订单类别:publicclassOrderpublicintIdget;set;publicin... 查看详情