I want to create a dynamic OData controller which can be inherited by concrete OData controllers. In order to do that, I need to way to select the proper DbSet from my DbContext and use it in the controller. However, I have no clue how to write this down in C#. This is what I tried:
Background is that there are two tables in the database with the exact same structure, but the requirement is to keep them apart since they contain different types of data. So I want a dynamic FileData controller where I can pass the desired type to and basically code everything once in the FileData controller.
Database context
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);
}
}
Controller
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);
}
}
No need for a custom method to do that, use the
DbContext.Set<T>
method.To fix your compile error you'll need to add a generic constraint to your controller class, like so:
Note the
where T : class
, this is required because theDbSet
class itself has thewhere TEntity : class
constraint