如何在EF Core / .NET Core 2.0中通过实体名称获取DbSet

23

我有一个带有若干个DbSet<T>属性的DbContext

public virtual DbSet<A> A { get; set; }
public virtual DbSet<B> B { get; set; }
public virtual DbSet<C> C { get; set; }
...
在某些情况下,我现在必须能够使用实体名称作为字符串来检索特定的DbSet(例如,当用户输入“A”时,我需要获取Dbset<A>)。
在以前的EF版本中,以下是可行的: var dbset = Context.Set(Type.GetType(A)); 在当前版本的EF Core中是否有类似的方法? 我已经尝试了几种方法来实现这一点,但目前唯一有效的方法是使用相当丑陋的开关/案例,我想摆脱它。
我在这里找到了几篇与此类似的帖子,但它们都与早期的.NET Core版本或EF5 / EF6有关。

1
我猜这个链接会有帮助:https://github.com/aspnet/EntityFrameworkCore/issues/2586 - JohnyL
好的,正如您从@JohnyL的链接中所看到的,仍然没有这样的方法。这是因为没有非泛型的DbSet类。问题是,您真的需要这样的方法吗?因为大多数DbSet<T>方法都与非泛型版本(AttachAddRemoveUpdateFind等)一起从DbContext公开,所以只使用实体类型的非泛型IQueryable可能会有问题。 - Ivan Stoev
感谢@JohnyL和ivan-stoev的帮助,这对我有很大帮助。虽然现在我更好地理解了为什么没有这样的方法,但我仍然同意GitHub上的最后一条评论 - 有时在设计时无法准确知道实体类型。 - lenniep
1个回答

23
执行以下操作将 "Set(Type t)" 扩展方法添加到 DbContext 类中:
using Microsoft.EntityFrameworkCore;

namespace ApiWebApplication.Utils
{
    public static class MyExtensions 
    {
        public static IQueryable<object> Set (this DbContext _context, Type t)
        {
            return (IQueryable<object>)_context.GetType().GetMethod("Set").MakeGenericMethod(t).Invoke(_context, null);
        }
    }
}

例子:

    // GET: api/Employees
    [HttpGet]
    public IEnumerable<object> GetEmployees()
    {
        return _context.Set(typeof(Employee));
    }

5
这将返回一个IQueryable而不是DbSet,那么怎样才能向该集合中添加实体呢?例如? - Darrell
@Darrell 它返回DbSet。 - Shimmy Weitzhandler
2
@ShimmyWeitzhandler 如果它被转换为IQueryable,它如何返回DbSet? - JKL
1
使用 .NET 6,此调用将引发“AmbiguousMatchException”异常 - 是否有其他方法可以在 .NET 6 中完成此操作? - Sam
4
@Sam DbContext.Set现在不止有一个签名,您需要指定签名,尝试像这样写: public static DbSet<T> GetDbSet<T>(this DbContext _context) where T : class =>(DbSet<T>)_context.GetType().GetMethod("Set", types: Type.EmptyTypes).MakeGenericMethod(typeof(T)).Invoke(_context, null); - Smokovsky

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接