简体   繁体   中英

Can I have generic method for any Table/Entity passed a parameter?

I have a controller class and has one method which has tableName as parameter. and can have switch cases for up to 30 tables/cases.

Controller

    public async Task<IActionResult> GetData(string tableName, string pRtUnique)
    {

        var tableEnum = Enum.Parse<AssetInitial>(tableName);
        switch (tableEnum )
        {
            case AssetInitial.Table1:
                return Ok(ApiResult<List<Table1>>.Success200(await _extractService.GetDataAsync<Table1>(pRtUnique)));
                break;
            case AssetInitial.Table2: ..... break;
            case AssetInitial.Table3: ..... break;
 

             case AssetInitial.Table30: ..... break;

        }

     
    }

Interface

 public interface IExtractService
    {
        public Task<List<TEntity>> GetDataAsync<TEntity>( string pRtUnique) where TEntity : BaseEntity;

}        

Implementation :

  public class ExtractService : IExtractService
    {
        private readonly DbContext _context;
        
   

        public ExtractService(DbContext  context)
        {
            _context = context;
        }

        public async Task<List<TEntity>> GetDataAsync<TEntity>(string pRtUnique) where TEntity : BaseEntity
        {
            return await _context.Set<TEntity>().Where(x => x.RtUnique== pRtUnique).ToListAsync();
        }

     

    }

Can I have generic one code/call from controller class based on table. Don't like simply have a switch statement for 30 conditions to just retrieve data from table. HI hope you have understood the challenge currently I am going with. Can I have one method call which should work for all tables?

You have a view options here to achieve what you are wanting.

  1. You can use EF and the DbContext.Set method
  2. You can created stored procedures/query for your table and what that method needs to call.
  3. Last you can create SQL expressions and insert the table name

The first looks like this:

DbContext.Set(System.Type.GetType("tableName"))

The second could be like this

var db = new DbContext();
var list = db.ExecuteStoreQuery<Obj>(Obj.sql);


class Obj
{
   public const string sql = @"select [tbl].[field] from [tbl]";
}

And last you could just make a sql query to send over and it will work just the same.

var query =$"select * from  {table} where <some_condition>"; 
var list = db.ExecuteStoreQuery<Obj>(query);

These all can work and achieve your goal of being able to pass a tableName into a method and get back generic object type results. I am sure there are other ways, but in the past I normally just create a string and make a custom sql query string and send to database using the ExecuteStoreQuery<>().

I solved with the help of reflection and MakeGenericMethod. Please refer the link for more details https://learn.microsoft.com/en-us/do.net/api/system.reflection.methodinfo.makegenericmethod?view.net-6.0

 public class EnityRepository<TEntity> : IEnityRepository<TEntity> where TEntity : BaseEntity
 {

   private readonly DContext _context;
    public EnityRepository(DContext  context)
    {
        _context = context;
    }

   public async Task<List<object>> GetDataAsync(string tablename, string pRtUnique)
    {
        List<TEntity> result = new List<TEntity>();
        var type = Assembly.GetExecutingAssembly().GetTypes().FirstOrDefault(t => t.Name == tablename);
        var tableSet = _context.Set<TEntity>(type);
        result = await tableSet.Where(x => x.RtUnique == pRtUnique).ToListAsync();
        return result.Cast<object>().ToList();
     }

}


   //Created extension method
  public static class ContextSetExtension
  {
    public static IQueryable<TEntity> Set<TEntity>(this HIVEiKYTCDContext _context, Type t) where TEntity : BaseEntity
    {
        var method = typeof(DContext).GetMethods().Single(p => p.Name == nameof(DContext.Set) && p.ContainsGenericParameters && !p.GetParameters().Any());
        method = method.MakeGenericMethod(t);
        var res = method.Invoke(_context, null);
        return (IQueryable<TEntity>)res;
      }
  }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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