关键词:
【中文标题】在 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... 查看详情