通用 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.
- 接口:创建了一个通用接口,其中包含一些方法和一个示例。
public interface IDataService<TEntity>
{
public Task<List<TEntity>> GeDataAsync();
}
- 实施:现在我的实施 class 如下所示,它基本上是从 Table1.
填充数据
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();
}
- 控制器:
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;
}
// ...................................
}
}
- Ajax 来自 jquery
的电话
这种方法至少有两个问题:
- 我必须再创建 19 个实现 classes(Table2Service,Table2Service...Table20Service)以从各自的 classes。 类 (Table2, Table3......Table20)
- 我无法在控制器 class 的构造函数中传递那么多 IDataService、DataService.. DataService。以后可能会有更多...
我要找的是:
- 一个通用接口
- 一个通用实现 class 为所有这 20 table 提供数据。
- 一个控制器和方法 GeDataAsync() return table 基于从 ajax 传递的 Table 名称产生结果。
非常感谢任何帮助。
要获得完全通用的解决方案,您需要进行一些更改。
- 您需要更改接口 - 使方法通用,而不是接口:
public interface IDataService
{
public Task<List<TEntity>> GeDataAsync<TEntity>() where TEntity : class;
}
此处需要通用约束才能使 EF 正常工作。
- 更改您的服务实施:
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 使用该实体类型。
- 现在你的控制器只需要
GenericService
(IDataService
) 的 1 个依赖项:
public class DataController : Controller
{
private IDataService _dataService;
public DataController(IDataService dataService)
{
_dataService = dataService;
}
}
- 唯一剩下的就是某种映射,将请求中的 table 名称映射到正确的实体类型以调用服务方法。据我所知,没有一些“特殊”方法可以使 EF 仅通过 table 名称与某些 table 一起工作,因此您最终会得到类似的
GetDataAsync()
操作实现控制器。
要使映射通用,您可以使用反射:
- 您在控制器操作中获得 table 名称。
- 拥有 table 名称,您应该获得要使用的实体的类型 - 通过一些映射(如
Dictionary<string, Type>
)或者检查 table(实体) class 是的。因此,您应该拥有 Type
变量,它是要使用的实体类型。
- 您可以在上下文 class 上找到
Set()
方法,通过调用 MakeGenericMethod()
并设置在第二步中获得的实体类型使其通用。
- 现在您可以使用
yourMethodInfo.Invoke()
调用通用 Set()
方法。
如果您进行反思,我建议将 table 名称传递给服务方法并在服务中完成所有这些工作。
我正在使用 EF 开发 .Net 核心应用程序,我必须从中获取大约 20 个 tables/Entities 数据,每个 table 都有不同的列。 假设Table是Table1,Table2,Table3……Table20.
- 接口:创建了一个通用接口,其中包含一些方法和一个示例。
public interface IDataService<TEntity>
{
public Task<List<TEntity>> GeDataAsync();
}
- 实施:现在我的实施 class 如下所示,它基本上是从 Table1. 填充数据
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();
}
- 控制器:
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;
}
// ...................................
}
}
- Ajax 来自 jquery 的电话
这种方法至少有两个问题:
- 我必须再创建 19 个实现 classes(Table2Service,Table2Service...Table20Service)以从各自的 classes。 类 (Table2, Table3......Table20)
- 我无法在控制器 class 的构造函数中传递那么多 IDataService、DataService.. DataService。以后可能会有更多...
我要找的是:
- 一个通用接口
- 一个通用实现 class 为所有这 20 table 提供数据。
- 一个控制器和方法 GeDataAsync() return table 基于从 ajax 传递的 Table 名称产生结果。
非常感谢任何帮助。
要获得完全通用的解决方案,您需要进行一些更改。
- 您需要更改接口 - 使方法通用,而不是接口:
public interface IDataService
{
public Task<List<TEntity>> GeDataAsync<TEntity>() where TEntity : class;
}
此处需要通用约束才能使 EF 正常工作。
- 更改您的服务实施:
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 使用该实体类型。
- 现在你的控制器只需要
GenericService
(IDataService
) 的 1 个依赖项:
public class DataController : Controller
{
private IDataService _dataService;
public DataController(IDataService dataService)
{
_dataService = dataService;
}
}
- 唯一剩下的就是某种映射,将请求中的 table 名称映射到正确的实体类型以调用服务方法。据我所知,没有一些“特殊”方法可以使 EF 仅通过 table 名称与某些 table 一起工作,因此您最终会得到类似的
GetDataAsync()
操作实现控制器。
要使映射通用,您可以使用反射:
- 您在控制器操作中获得 table 名称。
- 拥有 table 名称,您应该获得要使用的实体的类型 - 通过一些映射(如
Dictionary<string, Type>
)或者检查 table(实体) class 是的。因此,您应该拥有Type
变量,它是要使用的实体类型。 - 您可以在上下文 class 上找到
Set()
方法,通过调用MakeGenericMethod()
并设置在第二步中获得的实体类型使其通用。 - 现在您可以使用
yourMethodInfo.Invoke()
调用通用Set()
方法。
如果您进行反思,我建议将 table 名称传递给服务方法并在服务中完成所有这些工作。