[英]Entity Framework Core use Dbset without having T
我希望能夠在 Dbset 中使用類型而不是 T
例如 Dbset(myType) 而不是 DbSet
EF 核心 3.1 要求您使用 DbSet,並且所有功能都封裝在擴展方法中。
這是我為 EF 3.1 使用的解決方案
希望既然我已經經歷過痛苦,我可以為下一個必須這樣做的可憐靈魂分享我的解決方案。
用法
var dbSet = new DbSetFacade(myType);
dynamic results = await dbSet.ToListAsync();
我現在只分享 ToList,Count 以保持簡短!
public class DbSetFacade
{
private static ReadOnlyDictionary<EfQueryExtensionType, MethodInfo> _extensionMethodInfos = GetExtensionMethodInfos();
private readonly object _dbSet;
private readonly ReadOnlyDictionary<EfQueryExtensionType, MethodInfo> _genericInstanceMethodInfos;
public DbSetFacade(DbContext context, Type entityType)
{
if (context == null) throw new ArgumentNullException(nameof(context));
if (entityType == null) throw new ArgumentNullException(nameof(entityType));
_dbSet = GetDbSetInstance(context, entityType);
_genericInstanceMethodInfos = new ReadOnlyDictionary<EfQueryExtensionType, MethodInfo>(new Dictionary<EfQueryExtensionType, MethodInfo>
{
[EfQueryExtensionType.AsNoTracking] = _extensionMethodInfos[EfQueryExtensionType.AsNoTracking].MakeGenericMethod(entityType),
[EfQueryExtensionType.ToListAsync] = _extensionMethodInfos[EfQueryExtensionType.ToListAsync].MakeGenericMethod(entityType),
[EfQueryExtensionType.CountAsyncWithoutPredicate] = _extensionMethodInfos[EfQueryExtensionType.CountAsyncWithoutPredicate].MakeGenericMethod(entityType),
});
}
enum EfQueryExtensionType
{
AsNoTracking,
ToListAsync,
//FirstOrDefaultAsyncWithPredicate,
//FirstOrDefaultAsyncWithoutPredicate,
//ContainsAsync,
//CountAsyncWithPredicate,
CountAsyncWithoutPredicate
}
public Task<int> CountAsync(CancellationToken token = default) => _genericInstanceMethodInfos[EfQueryExtensionType.CountAsyncWithoutPredicate].Invoke(null, new object[] { _dbSet, token }) as Task<int>;
public async Task<dynamic> ToListAsync(CancellationToken token = default)
{
var noTrackingSet = _genericInstanceMethodInfos[EfQueryExtensionType.AsNoTracking].Invoke(null, new object[] { _dbSet });
var toList = _genericInstanceMethodInfos[EfQueryExtensionType.ToListAsync].Invoke(null, new object[] { noTrackingSet, token }) as Task;
await toList.ConfigureAwait(false);
return (object)((dynamic)toList).Result;
}
private static object GetDbSetInstance(DbContext context, Type type)
{
return typeof(DbContext).GetMethods()
.FirstOrDefault(p => p.Name == "Set" && p.ContainsGenericParameters)
.MakeGenericMethod(type)
.Invoke(context, null);
}
static ReadOnlyDictionary<EfQueryExtensionType, MethodInfo> GetExtensionMethodInfos()
{
var extensionMethods = typeof(EntityFrameworkQueryableExtensions)
.GetTypeInfo()
.GetMethods()
.Where(x => x.ContainsGenericParameters && x.GetParameters()[0].ParameterType.IsGenericType);
return new ReadOnlyDictionary<EfQueryExtensionType, MethodInfo>(new Dictionary<EfQueryExtensionType, MethodInfo>
{
[EfQueryExtensionType.AsNoTracking] = extensionMethods.FirstOrDefault(x => x.Name == "AsNoTracking"),
[EfQueryExtensionType.ToListAsync] = extensionMethods.FirstOrDefault(x => x.Name == "ToListAsync" && x.GetParameters().Count() == 2),
[EfQueryExtensionType.CountAsyncWithoutPredicate] = extensionMethods.FirstOrDefault(x => x.Name == "CountAsync" && x.GetParameters().Count() == 2)
});
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.