EF Core中的多个Includes()
我有一个扩展方法,允许您在EF中一般包含数据:
public static IQueryable IncludeMultiple(this IQueryable query, params Expression<Func>[] includes) where T : class { if (includes != null) { query = includes.Aggregate(query, (current, include) => current.Include(include)); } return query; }
这允许我在我的存储库中有这样的方法:
public Patient GetById(int id, params Expression<Func>[] includes) { return context.Patients .IncludeMultiple(includes) .FirstOrDefault(x => x.PatientId == id); }
我相信扩展方法在EF Core之前有效,但现在包括“children”就像这样:
var blogs = context.Blogs .Include(blog => blog.Posts) .ThenInclude(post => post.Author);
有没有办法改变我的通用扩展方法,以支持EF Core的新ThenInclude()
实践?
正如其他人的评论所述,您可以使用EF6代码来解析表达式并应用相关的Include
/ ThenInclude
调用。 毕竟它看起来并不那么难,但由于这不是我的想法,我宁愿不用它的代码回答。
您可以更改模式以显示某些界面,从而允许您从调用者指定包含而不让它访问底层可查询。
这将导致类似于:
using YourProject.ExtensionNamespace; // ... patientRepository.GetById(0, ip => ip .Include(p => p.Addresses) .ThenInclude(a=> a.Country));
using
命名空间必须与包含最后一个代码块中定义的扩展方法的命名空间名称匹配。
GetById
现在是:
public static Patient GetById(int id, Func, IIncludable> includes) { return context.Patients .IncludeMultiple(includes) .FirstOrDefault(x => x.EndDayID == id); }
扩展方法IncludeMultiple
:
public static IQueryable IncludeMultiple (this IQueryable query, Func, IIncludable> includes) where T : class { if (includes == null) return query; var includable = (Includable )includes(new Includable (query)); return includable.Input; }
Includable
类和接口,它们是简单的“占位符”,其他附加扩展方法将用于模拟EF Include
和ThenInclude
方法:
public interface IIncludable { } public interface IIncludable : IIncludable { } public interface IIncludable : IIncludable { } internal class Includable : IIncludable where TEntity : class { internal IQueryable Input { get; } internal Includable(IQueryable queryable) { // C# 7 syntax, just rewrite it "old style" if you do not have Visual Studio 2017 Input = queryable ?? throw new ArgumentNullException(nameof(queryable)); } } internal class Includable : Includable , IIncludable where TEntity : class { internal IIncludableQueryable IncludableInput { get; } internal Includable(IIncludableQueryable queryable) : base(queryable) { IncludableInput = queryable; } }
IIncludable
扩展方法:
using Microsoft.EntityFrameworkCore; // others using ommitted namespace YourProject.ExtensionNamespace { public static class IncludableExtensions { public static IIncludable Include( this IIncludable includes, Expression> propertySelector) where TEntity : class { var result = ((Includable )includes).Input .Include(propertySelector); return new Includable(result); } public static IIncludable ThenInclude( this IIncludable includes, Expression> propertySelector) where TEntity : class { var result = ((Includable)includes) .IncludableInput.ThenInclude(propertySelector); return new Includable(result); } public static IIncludable ThenInclude( this IIncludable> includes, Expression> propertySelector) where TEntity : class { var result = ((Includable>)includes) .IncludableInput.ThenInclude(propertySelector); return new Includable(result); } } }
IIncludable
几乎就像来自EF的IIncludableQueryable
,但它不扩展IQueryable
并且不允许重新整形查询。
当然,如果调用者在同一个程序IIncludable
,它仍然可以将IIncludable
为Includable
并开始摆弄可查询对象。 但是,如果有人想弄错,我们就无法阻止他这样做(reflection允许任何事情)。 重要的是暴露的合同。
现在,如果您不关心将IQueryable
暴露给调用者(我怀疑),显然只需更改您的params
参数以获取Func
参数,并避免对上述所有内容进行编码。
最好的结果:我没有测试过这个,我目前不使用Entity Framework!
对于后代而言,另一个不太有说服力但更简单的解决方案是利用使用navigationPropertyPath
的Include()
重载:
public static class BlogIncludes { public const string Posts = "Posts"; public const string Author = "Posts.Author"; } internal static class DataAccessExtensions { internal static IQueryable IncludeMultiple (this IQueryable query, params string[] includes) where T : class { if (includes != null) { query = includes.Aggregate(query, (current, include) => current.Include(include)); } return query; } } public Blog GetById(int ID, params string[] includes) { var blog = context.Blogs .Where(x => x.BlogId == id) .IncludeMultiple(includes) .FirstOrDefault(); return blog; }
存储库调用是:
var blog = blogRepository.GetById(id, BlogIncludes.Posts, BlogIncludes.Author);
当然有,
你可以遍历原始参数的表达式树,以及任何嵌套的包含,将它们添加为
.Include(entity => entity.NavigationProperty) .ThenInclude(navigationProperty.NestedNavigationProperty)
但它不是微不足道的,但绝对是非常可行的,请分享,如果你这样做,因为它可以明确地重复使用!
你可以这样做:
上述就是C#学习教程:EF Core中的多个Includes()分享的全部内容,如果对大家有所用处且需要了解更多关于C#学习教程,希望大家多多关注—计算机技术网(www.ctvol.com)!
public Patient GetById(int id, Func, IIncludableQueryable> includes = null) { IQueryable queryable = context.Patients; if (includes != null) { queryable = includes(queryable); } return queryable.FirstOrDefault(x => x.PatientId == id); } var patient = GetById(1, includes: source => source.Include(x => x.Relationship1).ThenInclude(x => x.Relationship2));
public Task> GetAll() { var query = _Db.Set().AsQueryable(); foreach (var property in _Db.Model.FindEntityType(typeof(TEntity)).GetNavigations()) query = query.Include(property.Name); return query.ToListAsync(); }
本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。
ctvol管理联系方式QQ:251552304
本文章地址:https://www.ctvol.com/cdevelopment/957273.html