EF Core 2.1 - для этого DbContext не настроен поставщик базы данных - PullRequest
0 голосов
/ 04 марта 2020

У меня ASP. Net Core 2.1 с EF Core 2.1. Вот так выглядит мой класс DbContext

app.DAL.EF -> Layer

using app.domain;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Design;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
using Microsoft.Extensions.Configuration;
using System;
using System.IO;

namespace app.EF
{
 public class MyAppContext : DbContext
 {
    public MyAppContext(DbContextOptions<MyAppContext> options)
    {
    }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.ApplyConfiguration(new CustomerConfiguration());
        modelBuilder.HasDefaultSchema("app");
        base.OnModelCreating(modelBuilder);
    }

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        base.OnConfiguring(optionsBuilder);
    }

    public DbSet<Customer> Customers { get; set; }
 }

   public class MyAppContextConfiguration : IDesignTimeDbContextFactory<MyAppContext>
   {
    public MyAppContext CreateDbContext(string[] args)
    {
        IConfigurationRoot configuration = new ConfigurationBuilder()
                                            .SetBasePath(Directory.GetCurrentDirectory())
                                            .AddJsonFile("appsettings.json", optional: false, true)
                                            .AddJsonFile($"appsettings.{Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT ") ?? "Production" }.json", optional: true)
                                            .Build();

        var optionsBuilder = new DbContextOptionsBuilder<MyAppContext>();
        //optionsBuilder.UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking);
        var dbConString = configuration.GetConnectionString("ITMDbConnection");

        optionsBuilder.UseSqlServer(dbConString);

        return new MyAppContext(optionsBuilder.Options);
    }
}

public class CustomerConfiguration : IEntityTypeConfiguration<Customer>
{
    public void Configure(EntityTypeBuilder<Customer> builder)
    {
        builder.HasKey(x => x.Id);
    }
}}

app.DI -> Layer

  public static class Factory
  {
    public static void Initialize(ref IServiceCollection services)
    {
        //services.AddTransient<MyAppContext>();
        services.AddDbContext<MyAppContext>(options =>
        {

        });
        //services.AddTransient<MyAppContextConfiguration>();
        services.AddTransient<ICustomerRepository, CustomerRepository>();
    }
}

app.API -> Layer

 namespace app.api
 {
 public class Startup
 {
     public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public IConfiguration Configuration { get; }

    // This method gets called by the runtime. Use this method to add services to the container.
    public void ConfigureServices(IServiceCollection services)
    {
        Factory.Initialize(ref services);
        services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
    }

    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }

        app.UseMvc();
    }
}}

При запуске Add-Migration DbInit из консоли диспетчера пакетов выдает следующую ошибку

Ни один поставщик базы данных не имеет был настроен для этого DbContext. Поставщик можно настроить, переопределив метод DbContext.OnConfiguring или используя AddDbContext в поставщике службы приложений. Если используется AddDbContext, то также убедитесь, что ваш тип DbContext принимает объект DbContextOptions в своем конструкторе и передает его базовому конструктору для DbContext.

error

Спасибо!

Ответы [ 3 ]

0 голосов
/ 04 марта 2020

Внутри ConfigureServices

services.AddDbContext<ApplicationDbContext>(options =>
    options.UseSqlServer(
        Configuration.GetConnectionString("DefaultConnection")));

В настройках приложения. json

{
    "ConnectionStrings": {
        "DefaultConnection": "SQL connection string"
    }
}
0 голосов
/ 04 марта 2020

Ошибка понятна - провайдер и соединение никогда не настраиваются. Весь этот код можно заменить следующим контекстом:

public class MyAppContext : DbContext
 {
    public DbSet<Customer> Customers { get; set; }

    public MyAppContext(){}

    public MyAppContext(DbContextOptions<MyAppContext> options)
        :base(options)
    {}

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        //The base method is empty
        modelBuilder.HasDefaultSchema("app");
    }
 }

И вызов AddDbContext внутри ConfigureServices:


 public class Startup
 {
     public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public IConfiguration Configuration { get; }

    // This method gets called by the runtime. Use this method to add services to the container.
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddDbContext<MyAppContext>(options =>
        {
            var dbConString = Configuration.GetConnectionString("ITMDbConnection");
            options.UseSqlServer(dbConString);
        });


        services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
    }

    ....

}

Хотя большинство приложений имеют более одного DbContext. Одним из вариантов будет добавление другого метода к Startup.cs для их регистрации. Для более сложных приложений, например приложений, состоящих из разных доменов / модулей / подсистем / проектов, лучшей идеей будет создание методов расширения, например:

public static CustomerDomainExtensions
{
    public static IServicesCollection AddCustomerDomain(this IServicesCollection services,IConfiguration configuration)
    {
        return services.AddCustomerContexts(configuration)
                       .AddRepositories(...)
                       ...;

    }

    public static AddCustomerContexts(this IServicesCollection services,IConfiguration configuration)
    {
        var dbConString = Configuration.GetConnectionString("ITMDbConnection");
        services.AddDbContext<MyAppContext>(options =>
        {
            options.UseSqlServer(dbConString);
        });
        //Add more contexts ...
    }
}

В Startup.cs это будет вызываться внутри ConfigureServices. Так работают все классы Microsoft.Extensions.*, предоставляя методы расширения Add и Use для использования в Startup.cs:

public void ConfigureServices(IServiceCollection services)
{
    services.AddCustomerDomain(Configuration);


    services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
}

EDIT

Добавлен конструктор по умолчанию в DbContext

0 голосов
/ 04 марта 2020

это просто то, что говорится - нет подключенного провайдера базы данных.

Посмотрите на весь ваш код. Где вы указываете поставщика базы данных? Что-то вроде UseSqlServer (в OnConfiguring для DbContext), в зависимости от того, какого поставщика базы данных вы хотите использовать.

...