升级.NET6至.NET7:EF7脚手架生成模型无setter的适配问题咨询
解决方案
针对EF Core 7脚手架生成的导航集合无setter导致排序代码失效的问题,有两个简单可行的方案,无需回退.NET版本或修改脚手架模板:
方案1:内存中修改现有集合(最小代码改动)
EF Core 7生成的导航集合通常实现了ICollection<T>接口,支持Clear()和Add()方法,因此可以通过清空原有集合再添加排序后的元素来替代赋值操作,修改后的排序代码如下:
public async Task<GetApprovalFormResponse<GetStaticErrorType>> GetAsync(GetApprovalFormRequest request) { var form = await storage.ApprovalForms .Include(s => s.ApprovalSections).ThenInclude(s => s.ApprovalQuestions) .Where(s => s.IdApprovalForm == request.IdApprovalForm) .FirstOrDefaultAsync(); if (form == null) { return new GetApprovalFormResponse<GetStaticErrorType> { Success = false, ApprovalForm = null }; } // 排序分类:清空后添加排序结果 var sortedSections = form.ApprovalSections.OrderBy(s => s.Order).ToList(); form.ApprovalSections.Clear(); foreach (var section in sortedSections) { form.ApprovalSections.Add(section); // 排序当前分类下的问题:同样清空后添加 var sortedQuestions = section.ApprovalQuestions.OrderBy(q => q.Order).ToList(); section.ApprovalQuestions.Clear(); foreach (var question in sortedQuestions) { section.ApprovalQuestions.Add(question); } } return new GetApprovalFormResponse<GetStaticErrorType> { Success = true, ApprovalForm = form }; }
这个方案几乎不需要改动原有查询逻辑,只是把赋值操作换成了集合的清空和添加,适配无setter的只读集合。
方案2:查询阶段直接排序(单查询完成)
如果希望在数据库查询阶段就完成排序,可以通过Select投影来构造包含排序后导航属性的实体,这样拿到的实体直接就是有序的,无需后续内存处理:
public async Task<GetApprovalFormResponse<GetStaticErrorType>> GetAsync(GetApprovalFormRequest request) { var form = await storage.ApprovalForms .Where(f => f.IdApprovalForm == request.IdApprovalForm) .Select(f => new ApprovalForm { // 复制ApprovalForm的所有必要属性 IdApprovalForm = f.IdApprovalForm, // 其他属性如Name、Description等按需添加 ApprovalSections = f.ApprovalSections .OrderBy(s => s.Order) .Select(s => new ApprovalSection { // 复制ApprovalSection的必要属性 IdApprovalSection = s.IdApprovalSection, Order = s.Order, // 其他属性 ApprovalQuestions = s.ApprovalQuestions .OrderBy(q => q.Order) .ToList() }) .ToList() }) .FirstOrDefaultAsync(); if (form == null) { return new GetApprovalFormResponse<GetStaticErrorType> { Success = false, ApprovalForm = null }; } return new GetApprovalFormResponse<GetStaticErrorType> { Success = true, ApprovalForm = form }; }
注意:需要手动复制实体的所有业务所需属性,因为是显式构造实体对象。如果实体属性较多,这个方案的代码量会稍大,但能减少内存中的排序操作。
内容的提问来源于stack exchange,提问作者Yannick Vachon
相关产品推荐
相关产品推荐

