我有一个具有签名的EF上下文
public class MyContext : DbContext, IDbContext
{
}
当我将它添加到服务时,我使用它
services.AddDbContext<MyContext>(op =>
{
op.UseSqlServer(configuration.GetConnectionString("DefaultConnection"));
});
但是当我注入IDbContext时会导致问题,比如
services.AddScoped(typeof(IDbContext), typeof(MyContext));
因为它复制了我的DbContext,而且每个请求应该只有一个。
我该如何解决?
答案 0 :(得分:5)
在您的情况下使用工厂方法应该可以正常工作。
services.AddScoped<IDbContext>(provider => provider.GetService(typeof(MyContext)));
通过这种方式,您将解析MyDbContext
的新实例(在第一次调用时)或在最终调用请求期间返回已实例化的实例。
答案 1 :(得分:0)
请注意,如果要注册多个不同的DbContext,则必须使用正确的特定DbContextOptions正确定义构造函数。如果您不这样做,则冒着被DI解决不正确类型的风险。
例如,我使用的是MyContext : DbContext, IDbContext
,类似于OP,但是我也使用的是通用的DbContext
用于OpenIddict的临时存储:
services.AddDbContext<DbContext>(o =>
{
o.UseInMemoryDatabase(nameof(DbContext)); //tokens and stuff is stored in memory, not the actual users or passwords.
o.UseOpenIddict();
});
至关重要的是,我的MyContext构造函数太通用了-使用Visual Studio快速操作模板创建的:( ugh
public MyContext (DbContextOptions options) : base(options) { ... }
这将导致DI在运行时解析错误的DbContext:
Microsoft.EntityFrameworkCore.Infrastructure:Information: Entity Framework Core 2.1.4-rtm-31024 initialized 'MyContext' using provider 'Microsoft.EntityFrameworkCore.InMemory' with options: StoreName=DbContext
有时候,我遇到一个错误,抱怨我的上下文没有正确的构造函数类型,因此我将构造函数更改为:
public MyContext (DbContextOptions<MyContext> options) : base(options) { ... }
,现在可以正常使用了。