简体   繁体   English

Entity Framework Core 在没有 T 的情况下使用 Dbset

[英]Entity Framework Core use Dbset without having T

I want to be able use a type instead of T with Dbset我希望能够在 Dbset 中使用类型而不是 T

For example Dbset(myType) instead of DbSet例如 Dbset(myType) 而不是 DbSet

EF core 3.1 requires you to use DbSet and all the functionality is encapsulated in Extension methods. EF 核心 3.1 要求您使用 DbSet,并且所有功能都封装在扩展方法中。

Here's a solution I went with for EF 3.1这是我为 EF 3.1 使用的解决方案

Hoping that since I've already been through the pain, I can share my solution for the next poor soul who has to do this.希望既然我已经经历过痛苦,我可以为下一个必须这样做的可怜灵魂分享我的解决方案。

Usage用法

var dbSet = new DbSetFacade(myType);
dynamic results = await dbSet.ToListAsync();

I'll just share ToList,Count for now to keep it brief!我现在只分享 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM