【发布时间】:2021-06-22 14:38:39
【问题描述】:
我想使用 GraphQL 和 Entity Framework Core 来查询多个数据库。每个数据库都链接到一个被许可人,因此所有查询都会收到一个查询参数licenseeId。现在我需要指示 DI 在服务请求 DbContext 时(例如通过构造函数参数或服务定位器)以某种方式基于 licenseeId 解析 DbContext。这真的可能吗?
以下是当前实施的相关部分:
存储库类
public MyRepository
{
public MyDbContext DbContext { get; set; }
public MyRepository(MyDbContext dbContext)
{
}
}
查询类
public class MainQuery : ObjectGraphType
{
public MainQuery()
{
objectGraph.FieldAsync<ListGraphType<MyModel>>("items",
arguments: new QueryArguments(
new QueryArgument<NonNullGraphType<GuidGraphType>> { Name = "licenseeId" }
),
resolve: async context => {
var licenseeId = resolveFieldContext.GetArgument<Guid>("licenseeId");
// *1, create dbContext based on licenseeId manually via factory
var dbContext = ...;
var repository = resolveFieldContext.ResolveServices.GetRequiredService<CucumberRepository>();
// *2, assign context manually
repository.DbContext = dbContext;
return await repository.GetAllAsync();
});
}
}
如您所见,我目前需要使用工厂 (*1) 手动创建 DbContext,然后将此实例分配给存储库属性 (*2)。
我想在这里使用纯 DI。我的想法是在 Startup 中以某种方式使用服务工厂
services.AddDbContext<MyDbContext>((serviceProvider, dbContextOptionsBuilder) => {
var query = serviceProvider.GetRequiredService<?>();
var connectionString = $"...;Catalog=MyDatabase_{query.GetLicenseeId()}";
dbContextOptionsBuilder.UseSqlServer(connectionString, ...);
});
这将使我能够像这样定义存储库类
public MyRepository
{
public MyRepository(MyDbContext dbContext)
{
}
}
在解析回调中我可以简单地写
objectGraph.FieldAsync<ListGraphType<MyModel>>(...,
resolve: async context => {
var repository = resolveFieldContext.ResolveServices.GetRequiredService<MyRepository>();
return await repository.GetAllAsync();
});
这是个好主意吗?
【问题讨论】:
-
存储库模式在这里是个坏主意。
-
@SvyatoslavDanyliv 是的,我知道,但我无法改变这一点。让我们专注于实际问题;)
-
@SvyatoslavDanyliv 您指出存储库模式在这里是一个坏主意。你有这个说法的参考吗?是不是因为 GraphQL 无法优化查询?
-
使用 EF 总是坏主意。我的意思是通用存储库模式。例如:rob.conery.io/2014/03/04/…
标签: c# dependency-injection graphql entity-framework-core