动态 select 来自 DbContext 的 DbSet 成员?

Dynamically select DbSet member from DbContext?

我想创建一个可以由具体 OData 控制器继承的动态 OData 控制器。为此,我需要从我的 DbContext 中找到 select 正确的 DbSet 并在控制器中使用它。但是,我不知道如何用 C# 写下来。这是我试过的:

背景是数据库中有两张结构完全相同的表,但要求将它们分开,因为它们包含不同类型的数据。所以我想要一个动态的 FileData 控制器,我可以在其中将所需的类型传递给并基本上在 FileData 控制器中对所有内容进行一次编码。

数据库上下文

    public class DS2DbContext : DbContext
    {
        public DbSet<DocumentFileData> DocumentFileData { get; set; }
        public DbSet<WatermarkFileData> WatermarkFileData { get; set; }
        public DS2DbContext(DbContextOptions<DS2DbContext> options) : base(options) { }
        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            base.OnModelCreating(modelBuilder);
        }
    }

控制器

    public class FileDataController<T> : ODataController
    {
        private readonly DS2DbContext _context;

        private readonly ILogger<FileDataController<T>> _logger;

        // --------------------------------------------------

        public FileDataController(DS2DbContext dbContext, ILogger<FileDataController<T>> logger)
        {
            _logger = logger;
            _context = dbContext;
        }

        public DbSet<T> DB()
        // Error CS0452: 
        // The type 'T' must be a reference type in order to use it as parameter
        // 'TEntity' in the generic type or method 'DbSet<TEntity>'
        {
            PropertyInfo pi = _context.GetType().GetProperty(nameof(T));
            MethodInfo mi = pi.GetGetMethod();
            return (DbSet<T>)mi.Invoke(this, null); // error CS0452
        }

        [EnableQuery(PageSize = 15)]
        public IQueryable<T> Get()
        {
            //return _db.FileData;
            return DB();
        }

        [EnableQuery]
        public SingleResult<WatermarkFileData> Get([FromODataUri] Guid ID)
        {
            //var result = _db.FileData.Where(c => c.ID == ID);
            var result = DB().Where(c => c.ID == ID);
            return SingleResult.Create(result);
        }
    }

无需自定义方法,使用 DbContext.Set<T> 方法。

要修复编译错误,您需要向控制器添加通用约束 class,如下所示:

public class FileDataController<T> : ODataController where T : class

注意 where T : class,这是必需的,因为 DbSet class 本身具有 where TEntity : class 约束