类型的 DbContext 不能被合并,因为它没有接受单个 DbContextOptions 类型参数的 public 构造函数
The DbContext of type cannot be pooled because it does not have a single public constructor accepting a single parameter of type DbContextOptions
我正在尝试将我们当前的 .Net Core 应用程序从 1.1 升级到 2.0,但收到此 运行 时间错误:"The DbContext of type 'CoreContext' cannot be pooled because it does not have a single public constructor accepting a single parameter of type DbContextOptions".
这是使用新的IServiceCollection.AddDbContextPool<>函数引起的。当我使用 IServiceCollection.AddDbContext<> 时它仍然有效。
此应用程序是 DB-First,因此我使用 'Scaffold-DbContext' 生成我们所有的上下文。因此,以及注入其他服务的需要,我在每个上下文中都有一个扩展,如下所示:
public partial class CoreContext
{
public CoreContext(
DbContextOptions<CoreContext> options,
IUserService userService,
IAuditRepository auditRepository
) : base(options) {...}
}
每当我 运行 Scaffold-DbContext 我只是从 CoreContext 中删除自动生成的构造函数,但即使我把它放在那里我仍然会收到这个错误。
public partial class CoreContext : DbContext
{
public CoreContext(DbContextOptions<CoreContext> options) : base(options) {}
}
我已经将 Program.cs 更新为新样式:
public class Program
{
public static void Main(string[] args)
{
BuildWebHost(args).Run();
}
public static IWebHost BuildWebHost(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseKestrel()
.UseContentRoot(Directory.GetCurrentDirectory())
.UseIISIntegration()
.UseStartup<Startup>()
.Build();
}
Startup.cs 非常简单:
public IServiceProvider ConfigureServices(IServiceCollection services)
{
...
services.AddDbContextPool<CoreContext>(options => options.UseSqlServer(absConnectionString));
...
}
如果有帮助,我正在使用 Autofac 进行 DI。现在我将默认返回到非池化替代方案,但利用此功能会很好。
尝试使用 AddDbContext
而不是 AddDbContextPool
。这在同样的情况下帮助了我。
services.AddDbContext<CoreContext>(options => options.UseSqlServer(absConnectionString));
"because it does not have a single public constructor accepting a
single parameter of type DbContextOptions"
如果除了接受 DbContextOptions 的构造函数之外还有任何 public 构造函数,您需要删除它们或使它们成为非 public 以便使用上下文池。
此外,通过重写 OnConfiguring 方法可以执行的操作也有限制。此处的文档中引用了这一点,但并未明确说明这些限制是什么:https://docs.microsoft.com/en-us/ef/core/what-is-new/index#dbcontext-pooling
使用 DbContext Pooling
时,您在派生 DbContext class 中的状态(例如私有字段)将被保留。这意味着您的服务生命周期现在是 singleton
。这就是为什么你不应该在这里有其他注入的服务。
但是可以通过这种方式查询所需的服务:
首先,我们应该在 DbContextOptionsBuilder
上使用 UseInternalServiceProvider
方法来告诉 EF 为其服务使用哪个服务提供商。此服务提供者必须为 EF 和任何提供者配置所有服务。所以我们应该手动注册 EF 服务:
services.AddEntityFrameworkSqlServer();
然后介绍应用程序的服务提供者,现在也包括 EF 服务:
services.AddDbContextPool<ApplicationDbContext>((serviceProvider, optionsBuilder) =>
{
optionsBuilder.UseSqlServer("...");
optionsBuilder.UseInternalServiceProvider(serviceProvider);
});
之后定义这些命名空间:
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.Extensions.DependencyInjection;
现在您可以在应用程序中访问已注册的服务
ApplicationDbContext class 使用以下方法
var siteSettings = this.GetService<IOptionsSnapshot<SiteSettings>>();
或
var siteSettings = this.GetInfrastructure().GetRequiredService<IOptionsSnapshot<SiteSettings>>();
this
是 DbContext 的当前实例。
这个问题主要发生在你“Scaffold-Dbcontext”生成两个构造函数的时候。
简单的解决方案:
AddDbContextPool:
如果您想使用 AddDbContextPool,请删除您的空构造函数并使用 DbContextOptionsBuilder 维护该构造函数。请注意,在这种情况下,您可能必须按照之前帖子中的建议提供选项。
AddDbContext:
使用 AddDbContext,您可以同时拥有 constructors/Overloads
注意:出于性能原因,AddDbContextPool是首选!
删除 DbContext 中的默认构造函数 class,这对我有用
我正在尝试将我们当前的 .Net Core 应用程序从 1.1 升级到 2.0,但收到此 运行 时间错误:"The DbContext of type 'CoreContext' cannot be pooled because it does not have a single public constructor accepting a single parameter of type DbContextOptions".
这是使用新的IServiceCollection.AddDbContextPool<>函数引起的。当我使用 IServiceCollection.AddDbContext<> 时它仍然有效。
此应用程序是 DB-First,因此我使用 'Scaffold-DbContext' 生成我们所有的上下文。因此,以及注入其他服务的需要,我在每个上下文中都有一个扩展,如下所示:
public partial class CoreContext
{
public CoreContext(
DbContextOptions<CoreContext> options,
IUserService userService,
IAuditRepository auditRepository
) : base(options) {...}
}
每当我 运行 Scaffold-DbContext 我只是从 CoreContext 中删除自动生成的构造函数,但即使我把它放在那里我仍然会收到这个错误。
public partial class CoreContext : DbContext
{
public CoreContext(DbContextOptions<CoreContext> options) : base(options) {}
}
我已经将 Program.cs 更新为新样式:
public class Program
{
public static void Main(string[] args)
{
BuildWebHost(args).Run();
}
public static IWebHost BuildWebHost(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseKestrel()
.UseContentRoot(Directory.GetCurrentDirectory())
.UseIISIntegration()
.UseStartup<Startup>()
.Build();
}
Startup.cs 非常简单:
public IServiceProvider ConfigureServices(IServiceCollection services)
{
...
services.AddDbContextPool<CoreContext>(options => options.UseSqlServer(absConnectionString));
...
}
如果有帮助,我正在使用 Autofac 进行 DI。现在我将默认返回到非池化替代方案,但利用此功能会很好。
尝试使用 AddDbContext
而不是 AddDbContextPool
。这在同样的情况下帮助了我。
services.AddDbContext<CoreContext>(options => options.UseSqlServer(absConnectionString));
"because it does not have a single public constructor accepting a single parameter of type DbContextOptions"
如果除了接受 DbContextOptions 的构造函数之外还有任何 public 构造函数,您需要删除它们或使它们成为非 public 以便使用上下文池。
此外,通过重写 OnConfiguring 方法可以执行的操作也有限制。此处的文档中引用了这一点,但并未明确说明这些限制是什么:https://docs.microsoft.com/en-us/ef/core/what-is-new/index#dbcontext-pooling
使用 DbContext Pooling
时,您在派生 DbContext class 中的状态(例如私有字段)将被保留。这意味着您的服务生命周期现在是 singleton
。这就是为什么你不应该在这里有其他注入的服务。
但是可以通过这种方式查询所需的服务:
首先,我们应该在 DbContextOptionsBuilder
上使用 UseInternalServiceProvider
方法来告诉 EF 为其服务使用哪个服务提供商。此服务提供者必须为 EF 和任何提供者配置所有服务。所以我们应该手动注册 EF 服务:
services.AddEntityFrameworkSqlServer();
然后介绍应用程序的服务提供者,现在也包括 EF 服务:
services.AddDbContextPool<ApplicationDbContext>((serviceProvider, optionsBuilder) =>
{
optionsBuilder.UseSqlServer("...");
optionsBuilder.UseInternalServiceProvider(serviceProvider);
});
之后定义这些命名空间:
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.Extensions.DependencyInjection;
现在您可以在应用程序中访问已注册的服务 ApplicationDbContext class 使用以下方法
var siteSettings = this.GetService<IOptionsSnapshot<SiteSettings>>();
或
var siteSettings = this.GetInfrastructure().GetRequiredService<IOptionsSnapshot<SiteSettings>>();
this
是 DbContext 的当前实例。
这个问题主要发生在你“Scaffold-Dbcontext”生成两个构造函数的时候。
简单的解决方案:
AddDbContextPool: 如果您想使用 AddDbContextPool,请删除您的空构造函数并使用 DbContextOptionsBuilder 维护该构造函数。请注意,在这种情况下,您可能必须按照之前帖子中的建议提供选项。
AddDbContext: 使用 AddDbContext,您可以同时拥有 constructors/Overloads
注意:出于性能原因,AddDbContextPool是首选!
删除 DbContext 中的默认构造函数 class,这对我有用