通用 Interface/Implementation class/Method returns 不同的结果集

Generic Interface/Implementation class/Method returns different result set

我正在使用 EF 开发 .Net 核心应用程序,我必须从中获取大约 20 个 tables/Entities 数据,每个 table 都有不同的列。 假设Table是Table1,Table2,Table3……Table20.

  1. 接口:创建了一个通用接口,其中包含一些方法和一个示例。
    public interface IDataService<TEntity>
    {
        public Task<List<TEntity>> GeDataAsync();
    }  
  1. 实施:现在我的实施 class 如下所示,它基本上是从 Table1.
  2. 填充数据
 public class Table1Service : IDataService<Table1>
    {
        private readonly ModelContext _context;
        
        public Table1Service(ModelContext context)
        {
            _context = context;

        }

 public async Task<List<Table1>> GeDataAsync();
        {
           
            return await _context.Table1s().ToListAsync();

        }

  1. 控制器:
public class DataController : Controller
{

  private IDataService<Table1> _table1Service;
 public DataController(IDataService<Table1> table1Service; )
        {
            _table1Service = table1Service;
        
        }

    [HttpGet("GeDataAsync")]
 public async Task<IActionResult> GeDataAsync( string tableName; )
        {
 var tableEnum = Enum.Parse<TableNames>(tableName); //;
     switch (tableEnum)
            {
                case TableNames.Table1:

                       return Ok(ApiResult<List<Table1>>.Success200(await _table1Service.GeDataAsync()));
                    break;
                
            }
       // ...................................
        }


}
  1. Ajax 来自 jquery
  2. 的电话

这种方法至少有两个问题:

  1. 我必须再创建 19 个实现 classes(Table2Service,Table2Service...Table20Service)以从各自的 classes。 类 (Table2, Table3......Table20)
  2. 我无法在控制器 class 的构造函数中传递那么多 IDataService、DataService.. DataService。以后可能会有更多...

我要找的是:

  1. 一个通用接口
  2. 一个通用实现 class 为所有这 20 table 提供数据。
  3. 一个控制器和方法 GeDataAsync() return table 基于从 ajax 传递的 Table 名称产生结果。

非常感谢任何帮助。

要获得完全通用的解决方案,您需要进行一些更改。

  1. 您需要更改接口 - 使方法通用,而不是接口:
public interface IDataService
{
    public Task<List<TEntity>> GeDataAsync<TEntity>() where TEntity : class;
}

此处需要通用约束才能使 EF 正常工作。

  1. 更改您的服务实施:
public class GenericService : IDataService
{
    private readonly ModelContext _context;
            
    public GenericService(ModelContext context)
    {
        _context = context;
    }
    
    public async Task<List<TEntity>> GeDataAsync<TEntity>() where TEntity : class =>                
        await _context.Set<TEntity>().ToListAsync();
}

您可以在上下文中调用 Set() 方法来指向 EF 使用该实体类型。

  1. 现在你的控制器只需要 GenericService(IDataService) 的 1 个依赖项:
public class DataController : Controller
{
    private IDataService _dataService;

    public DataController(IDataService dataService)
    {
        _dataService = dataService;
    }
}
  1. 唯一剩下的就是某种映射,将请求中的 table 名称映射到正确的实体类型以调用服务方法。据我所知,没有一些“特殊”方法可以使 EF 仅通过 table 名称与某些 table 一起工作,因此您最终会得到类似的 GetDataAsync() 操作实现控制器。

要使映射通用,您可以使用反射:

  1. 您在控制器操作中获得 table 名称。
  2. 拥有 table 名称,您应该获得要使用的实体的类型 - 通过一些映射(如 Dictionary<string, Type>)或者检查 table(实体) class 是的。因此,您应该拥有 Type 变量,它是要使用的实体类型。
  3. 您可以在上下文 class 上找到 Set() 方法,通过调用 MakeGenericMethod() 并设置在第二步中获得的实体类型使其通用。
  4. 现在您可以使用 yourMethodInfo.Invoke() 调用通用 Set() 方法。

如果您进行反思,我建议将 table 名称传递给服务方法并在服务中完成所有这些工作。