类型的DbContext无法合并,因为它没有单个公共构造函数接受DbContextOptions类型的单个参数

Jef*_*nke 7 entity-framework-core asp.net-core .net-core-2.0

我正在尝试将当前的.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) {...}
}
Run Code Online (Sandbox Code Playgroud)

每当我运行Scaffold-DbContext时,我只是从CoreContext中删除自动生成的构造函数,但即使我把它放在那里我仍然会收到此错误.

public partial class CoreContext : DbContext
{
    public CoreContext(DbContextOptions<CoreContext> options) : base(options) {}
}
Run Code Online (Sandbox Code Playgroud)

我已经将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();
}
Run Code Online (Sandbox Code Playgroud)

而Startup.cs非常简单:

public IServiceProvider ConfigureServices(IServiceCollection services)
{
    ...
    services.AddDbContextPool<CoreContext>(options => options.UseSqlServer(absConnectionString));
    ...
}
Run Code Online (Sandbox Code Playgroud)

如果有帮助,我正在使用Autofac进行DI.现在我将默认回到非Pooling替代方案,但是利用这个功能会很好.

C.I*_*ngo 21

删除 DbContext 类中的默认构造函数,这对我有用


Vah*_*idN 16

使用时DbContext Pooling,将保留派生的DbContext类中您自己的状态(例如私有字段).这意味着您的服务的生命周期singleton.这就是为什么你不应该在这里注入其他服务.但是可以通过这种方式查询所需的服务:首先,我们应该使用该UseInternalServiceProvider方法DbContextOptionsBuilder告诉EF哪个服务提供商用于其服务.此服务提供商必须具有为EF和任何提供商配置的所有服务.所以我们应该手动注册EF服务:

services.AddEntityFrameworkSqlServer();
Run Code Online (Sandbox Code Playgroud)

然后介绍现在包含EF服务的应用程序服务提供商:

services.AddDbContextPool<ApplicationDbContext>((serviceProvider, optionsBuilder) =>
{
   optionsBuilder.UseSqlServer("...");
   optionsBuilder.UseInternalServiceProvider(serviceProvider);
});
Run Code Online (Sandbox Code Playgroud)

之后定义这些名称空间:

using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.Extensions.DependencyInjection;
Run Code Online (Sandbox Code Playgroud)

现在,您可以使用以下方法访问ApplicationDbContext类中应用程序中的已注册服务

var siteSettings = this.GetService<IOptionsSnapshot<SiteSettings>>();
Run Code Online (Sandbox Code Playgroud)

要么

var siteSettings = this.GetInfrastructure().GetRequiredService<IOptionsSnapshot<SiteSettings>>();
Run Code Online (Sandbox Code Playgroud)

this 是DbContext的当前实例.

  • 不错的答案 +1,但应该添加一个说明,`optionsBuilder.UseInternalServiceProvider(serviceProvider)` 不是必需的,调用 `GetService&lt;T&gt;` 将从默认提供程序解析。 (4认同)

Rob*_*Rob 11

“因为它没有接受 DbContextOptions 类型的单个参数的单个公共构造函数”

如果除了接受 DbContextOptions 的构造函数之外还有任何公共构造函数,则需要删除它们或将它们设为非公共构造函数以使用上下文池。

此外,通过覆盖 OnConfiguring 方法可以完成的操作也有限制。此处的文档中对此进行了引用,但并未明确说明这些限制是什么:https : //docs.microsoft.com/en-us/ef/core/what-is-new/index#dbcontext-pooling

  • 问题是 Scaffold-DbContext 将额外的构造函数放入 (6认同)
  • 完美的答案。此错误应该显示为“因为它有多个公共...”,而不是它的读取方式。在我们的文化中,“因为你没有一个 X”读起来就像“X 或更多都可以,但你有零”,例如:“因为你没有一美元,你就破产了”……而当前的短语是准确的,但在我们的文化中本质上也是模糊的。 (2认同)