实体框架核心的DbContext继承问题与构造DbOptions

问题描述 投票:1回答:1

在我们的项目,我们有我们使用DB第一种方法的数据库。由于我们使用的不要让脚手架功能我有一个从产生一个继承了第二的DbContext。这使我避免手动每一个数据库变化发生时操纵所产生的分贝上下文。

因此,在启动时的类定义和用法是这样的:

  // the db context generated by scaffolding the database
  public partial class ApplicationDatabaseContextGenerated : DbContext
  {
    public ApplicationDatabaseContextGenerated() {}
    public ApplicationDatabaseContextGenerated(DbContextOptions<ApplicationDatabaseContextGenerated> options) : base(options) {}

    // the db sets scaffolded
  }

  // the db context used by the app with the extended functionality
  public class ApplicationDatabaseContext : ApplicationDatabaseContextGenerated
  {

    public ILogger<ApplicationDatabaseContext> Logger { get; protected set; }

    public ApplicationDatabaseContext() : base() {}

    public ApplicationDatabaseContext(DbContextOptions<ApplicationDatabaseContext> options, ILogger<ApplicationDatabaseContext> logger) : base(options)
    {
      Logger = logger ?? throw new ArgumentNullException(nameof(logger));
    }

    // the extended functionality like views and functions

  }

  // how I use it in startup
  public void ConfigureServices(IServiceCollection services)
  {
    // other things ...

    services.AddDbContext<ApplicationDatabaseContext>(options => options.UseNpgsql(Configuration.GetConnectionString("db1-connection")));

    // other things ...
  }

这不幸导致编译错误突出应用程序数据库上下文构造说明的基础(选项):

Error CS1503 Argument 1: cannot convert from 'Microsoft.EntityFrameworkCore.DbContextOptions<... ApplicationDatabaseContext>' to 'Microsoft.EntityFrameworkCore.DbContextOptions<... ApplicationDatabaseContextGenerated>'

我想,我们是聪明的,一个ApplicationDatabaseContextGenerated基本上是一个数据库上下文,改变了ApplicationDatabaseContextGenerated到的构造函数:

  public ApplicationDatabaseContextGenerated(DbContextOptions<DbContext> options) : base(options) {}

不,这是不允许的既不并导致:

Error CS1503 Argument 1: cannot convert from 'Microsoft.EntityFrameworkCore.DbContextOptions<... ApplicationDatabaseContext>' to 'Microsoft.EntityFrameworkCore.DbContextOptions<Microsoft.EntityFrameworkCore.DbContext>'

好吧,让我们采取既作为的DbContext

  // the db context generated by scaffolding the database
  public partial class ApplicationDatabaseContextGenerated : DbContext
  {
    public ApplicationDatabaseContextGenerated() {}
    public ApplicationDatabaseContextGenerated(DbContextOptions<DbContext> options) : base(options) {}

    // the db sets scaffolded
  }

  // the db context used by the app with the extended functionality
  public class ApplicationDatabaseContext : ApplicationDatabaseContextGenerated
  {

    public ILogger<ApplicationDatabaseContext> Logger { get; protected set; }

    public ApplicationDatabaseContext() : base() {}

    public ApplicationDatabaseContext(DbContextOptions<DbContext> options, ILogger<ApplicationDatabaseContext> logger) : base(options)
    {
      Logger = logger ?? throw new ArgumentNullException(nameof(logger));
    }

    // the extended functionality like views and functions

  }

漂亮,那编译。让我们先从它,我们得到:

  System.InvalidOperationException: No database provider has been configured for this DbContext. A provider can be configured by overriding the DbContext.OnConfiguring method or by using AddDbContext on the application service provider. If AddDbContext is used, then also ensure that your DbContext type accepts a DbContextOptions<TContext> object in its constructor and passes it to the base constructor for DbContext.
    at Microsoft.EntityFrameworkCore.Internal.DbContextServices.Initialize(IServiceProvider scopedProvider, IDbContextOptions contextOptions, DbContext context)
    at Microsoft.EntityFrameworkCore.DbContext.get_InternalServiceProvider()
    at Microsoft.EntityFrameworkCore.DbContext.get_DbContextDependencies()
    at Microsoft.EntityFrameworkCore.DbContext.get_Model()
    at Microsoft.EntityFrameworkCore.Internal.InternalDbQuery`1.get_EntityType()
    at Microsoft.EntityFrameworkCore.Internal.InternalDbQuery`1.get_EntityQueryable()
    at Microsoft.EntityFrameworkCore.Internal.InternalDbQuery`1.System.Linq.IQueryable.get_Provider()
    at Microsoft.EntityFrameworkCore.EntityFrameworkQueryableExtensions.ExecuteAsync[TSource,TResult](MethodInfo operatorMethodInfo, IQueryable`1 source, CancellationToken cancellationToken)
    at Microsoft.EntityFrameworkCore.EntityFrameworkQueryableExtensions.SingleAsync[TSource](IQueryable`1 source, CancellationToken cancellationToken)
    at ... MyMethod(ApplicationDatabaseContext dbContext, CancellationToken cancellationToken) in myfile.cs:line 51
    at ... MyOtherMethod in myfile.cs:line 61

那么,如何转换DbContextOptions或如何继承DbContexts?

entity-framework .net-core entity-framework-core asp.net-core-2.1 entity-framework-core-2.1
1个回答
2
投票

DbContextOptions<TContext>是一个通用的类,并且当它不支持协方差的任何类,因此可以DbContextOptions<TDerivedContext>不会被视为DbContextOptions<TBaseContext>

的解决方案是使用非通用DbContextOptions类在碱上下文构造(类似于DbContext类构造带选项):

public ApplicationDatabaseContextGenerated(DbContextOptions options) : base(options) { }

由于AddDbContext<ApplicationDatabaseContext>将创建DbContextOptions<ApplicationDatabaseContext>类的实例,该ApplicationDatabaseContext类的构造函数可以使用DbContextOptions<ApplicationDatabaseContext>DbContextOptions参数选项。

© www.soinside.com 2019 - 2024. All rights reserved.