c# - 不知道如何遍历 DbContext 中的类型,一般调用 ToListAsync
问题描述
我有一个带有国家属性的 DbContext
public DbSet<Country> Countries { get; set; }
我想使用反射ToListAsync
在我的上下文中调用每种类型的方法
我正在研究一种方法,该方法将对 DbContext 中的所有表进行快照,包括过滤表达式。已经使用 EntityQueryFilterHelper 处理了过滤
我正在为 .NET Core 3.1 使用 Ef Core
感谢答案中的帮助,我现在有了代码
var contextDictionary = new Dictionary<string, object>();
var allCountries = await this.Countries.ToListAsync();
var firstCountry = allCountries.FirstOrDefault();
var filters = new List<FilterObject>
{
new FilterObject() {PropertyName = "Name", PropertyValue = firstCountry.Name}
};
var entityTypes = this.Model.GetEntityTypes().Where(x => x.Name.Contains("Country"));
foreach (var entityType in entityTypes)
{
var requiredType = entityType.GetType();
var filter = EntityQueryFilterHelper.CreateFilter<Country>(filters);
var allItems = from x in this.Countries select x;
var filteredItems = filter(allItems);
var method = typeof(EntityFrameworkQueryableExtensions).GetMethod(nameof(EntityFrameworkQueryableExtensions.ToListAsync))?.MakeGenericMethod(typeof(Country));
var toListAsyncResult = (Task<List<Country>>) method?.Invoke(null, new object[] {filteredItems, default(CancellationToken)});
if (toListAsyncResult != null)
{
var result = await toListAsyncResult;
contextDictionary.Add("Countries", result);
}
}
这完美地工作 - 所以下一个问题是如何更改上述内容以使用 EntityType 而不是硬编码
有人可以帮忙吗?
保罗
解决方案
在ToListAync()
课堂EntityFrameworkQueryableExtensions
上,所以
var method = typeof(EntityFrameworkQueryableExtensions).GetMethod(nameof(EntityFrameworkQueryableExtensions.ToListAsync)).MakeGenericMethod(typeof(Country));
它是static
,所以:
var result = method.Invoke(null, new object[] { this.Countries, default(CancellationToken) });
哪里result
是Task<List<Country>>
一个Task
。
调用它很困难 :-) 从技术上讲,调用该方法很容易……提取结果很难。如果您想完全动态化,它会很快变得困难:
var t = (Task)method.Invoke(null, new object[] { context.Blogs, default(CancellationToken) });
await t;
var ilist = (IList)((dynamic)t).Result;
现在你是一个非泛型的IList
,所以它的元素是object
. 但最终你走错了方向。如果您想朝着“正确”的方向前进,请执行以下操作:
public static async void DoWorkOnMyIQueryable<T>(IQueryable<T> dbset)
{
List<T> res = await dbset.ToListAsync();
foreach (var el in res)
{
// Do something
}
}
并调用DoWorkOnMyIQueryable
通过反射。现在至少你有一个 typed List<T>
!
现在您已经写出了完整的问题,通常情况下,这是一个XY 问题。
正如我所写的,构建一个基于泛型的单个泛型方法TEntity
然后使用反射来调用它要容易得多。
方法:
public static class Tools
{
public static async Task<IList> ExtractData<TEntity>(DbContext context, List<FilterObject> filters) where TEntity : class
{
var dbset = context.Set<TEntity>();
var filter = EntityQueryFilterHelper.CreateFilter<TEntity>(filters);
var filtered = filter(dbset);
return await filtered.ToListAsync();
}
}
现在称之为:
public async Task<Dictionary<string, IList>> GenerateContextDictionary()
{
var filters = new List<FilterObject>();
// Here prepare your filters
var entityTypes = this.Model.GetEntityTypes().Where(x => x.Name.Contains("Country"));
var method = typeof(Tools).GetMethod(nameof(Tools.ExtractData), BindingFlags.Public | BindingFlags.Static);
var contextDictionary = new Dictionary<string, IList>();
foreach (var entityType in entityTypes)
{
var method2 = method.MakeGenericMethod(entityType.ClrType);
var ilist = await (Task<IList>)method2.Invoke(null, new object[] { this, filters });
contextDictionary.Add(entityType.Name, ilist);
}
return contextDictionary;
}
推荐阅读
- makefile - 编译tbb项目时出现cmake命令问题
- pine-script - 如何隐藏 RSI 条上的彩色零
- python - 我认为为什么会出现这种词性错误,我该如何解决
- ios - 给定一个自定义形状,如何增加尺寸以适应 SwiftUI 中的框架?
- python - 如何使用python在默认程序中打开多个文件
- javascript - 如何使用 Cognito 在 AWS Amplify Vuejs 应用程序中检查当前用户并加载用户数据
- java - 如何反转一个整数?
- javascript - 检查或统计所选文件少于 2 个
- javascript - ChartJs:如何在自动跳过设置为 true 时强制显示标签
- javascript - 在使用 tablesorter 排序的表中使用输入元素时,如何使用 inputmask 获取输入元素以不将更改恢复为先前的值?