【问题标题】:Entity Framework Core DbContext inheritance problem with DbOptions in constructor实体框架核心 DbContext 继承问题与构造函数中的 DbOptions
【发布时间】:2019-02-11 20:27:03
【问题描述】:

在我们的项目中,我们有一个使用数据库优先方法的数据库。由于我们使用的功能不会被搭建,所以我有第二个 DBContext,它继承自生成的 DBContext。这让我可以避免每次发生数据库更改时手动操作生成的数据库上下文。

所以 StartUp 中的类定义和用法如下所示:

  // 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 ...
  }

不幸的是,这会导致编译错误,突出显示 ApplicationDatabaseContext 构造函数的基础(选项):

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】:

    DbContextOptions&lt;TContext&gt; 是一个通用的,并且作为任何类它不支持协方差,因此DbContextOptions&lt;TDerivedContext&gt; 不能被视为DbContextOptions&lt;TBaseContext&gt;

    解决方案是在基本上下文构造函数中使用非泛型 DbContextOptions 类(类似于带有选项的DbContext 类构造函数):

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

    由于AddDbContext&lt;ApplicationDatabaseContext&gt; 将创建DbContextOptions&lt;ApplicationDatabaseContext&gt; 类的实例,因此ApplicationDatabaseContext 类构造函数可以使用DbContextOptions&lt;ApplicationDatabaseContext&gt;DbContextOptions 选项参数。

    【讨论】:

    • public ApplicationDatabaseContextGenerated(DbContextOptions options) : base(options) { } 似乎也有效
    猜你喜欢
    • 1970-01-01
    • 2022-11-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-22
    • 1970-01-01
    • 2016-11-27
    • 2016-10-28
    相关资源
    最近更新 更多