我正在尝试将当前的.Net Core应用程序从1.1升级到2.0并且遇到此运行时错误:"类型为' CoreContext的DbContext'无法汇集,因为它没有一个公共构造函数接受类型为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.c更新为新样式:
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。现在我将默认回到非Pooling的替代方案,但是利用这个功能会很好。
答案 0 :(得分:12)
使用DbContext Pooling
时,将保留派生的DbContext类中您自己的状态(例如私有字段)。这意味着您的服务的生命周期现在为singleton
。这就是为什么你不应该在这里注入其他服务的原因。
但是可以通过这种方式查询所需的服务:
首先,我们应该使用UseInternalServiceProvider
上的DbContextOptionsBuilder
方法告诉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类使用以下方法
var siteSettings = this.GetService<IOptionsSnapshot<SiteSettings>>();
或
var siteSettings = this.GetInfrastructure().GetRequiredService<IOptionsSnapshot<SiteSettings>>();
this
是DbContext的当前实例。
答案 1 :(得分:2)
&#34;因为它没有一个公共构造函数接受DbContextOptions类型的单个参数&#34;
如果除了接受DbContextOptions的公共构造函数之外还有任何公共构造函数,则需要删除它们或将它们设置为非公共构造函数才能使用上下文池。
此外,通过覆盖OnConfiguring方法可以做什么也有限制。这在此处的文档中引用,但它没有明确说明这些限制是什么:https://docs.microsoft.com/en-us/ef/core/what-is-new/index#dbcontext-pooling
答案 2 :(得分:1)
当您“ Scaffold-Dbcontext”并生成两个构造函数时,通常会遇到此问题。
简单解决方案: 1. AddDbContextPool : 如果要使用AddDbContextPool,请删除空的构造函数,并使用DbContextOptionsBuilder进行维护。请注意,在这种情况下,您可能必须提供如先前文章中所建议的选项。
注意:出于性能的原因,首选 AddDbContextPool !
答案 3 :(得分:0)
尝试使用AddDbContext
代替AddDbContextPool
。这帮助了我同样的情况。
services.AddDbContext<CoreContext>(options => options.UseSqlServer(absConnectionString));
答案 4 :(得分:0)
删除DbContext类中的默认构造函数,这对我有用