> VS 2017 и ASP.Net Core 2.1 и Entity Framework - я не хочу жестко кодировать строку подключения - PullRequest
0 голосов
/ 19 декабря 2018

У меня ASP.Net Core 2.1, использующий Entity Framework с интерфейсом Angular 5 и контроллером Web Api для серверной части.

Работает нормально, как есть, но теперь я хочу изменить его, чтобы строка подключения к базе данных НЕ была жестко закодирована.

Я следую за этим: https://docs.microsoft.com/en-us/ef/core/miscellaneous/connection-strings

Но этоне работает.Я получаю:

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

'((Microsoft.EntityFrameworkCore.Internal.InternalDbSet) db.TblEmployee) .Local 'сгенерировал исключение типа' System.InvalidOperationException '

Логические пути:

  1. Появится домашняя страница.Затем я нажимаю на пункт меню «Текущие сотрудники».
  2. Он переходит в службу Angular и выполняет метод getEmployees (), который выполняет метод веб-API.
  3. Он переходит к веб-APIконтроллер и выполняет метод - GetAllEmployee (), который выполняет метод слоев доступа к данным сотрудника.
  4. Он переходит к классу уровня доступа к данным сотрудника (я создаю экземпляр dbContext здесь).У меня есть точка останова в операторе возврата.Если я наведу курсор мыши на оператор return, я увижу ошибку.И, конечно, когда я продолжаю, приложение не работает.

enter image description here

enter image description here

enter image description here

enter image description here

Мой класс контекста базы данных:

namespace Angular5NetcoreEF.Models
{
public partial class DBAngular5NetcoreEFContext : DbContext
{
    public DBAngular5NetcoreEFContext()
    {
    }

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

    public virtual DbSet<TblCities> TblCities { get; set; }
    public virtual DbSet<TblEmployee> TblEmployee { get; set; }

    //protected override void OnConfiguring(DbContextOptionsBuilder 
    optionsBuilder)
    //{
    //    if (!optionsBuilder.IsConfigured)
    //    {
    //        optionsBuilder.UseSqlServer("Server=  
    //        (localdb)\\mssqllocaldb;Database=DBAngular5NetcoreEF;
    //        Trusted_Connection=True; MultipleActiveResultSets=true");
    //    }
    //} 

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<TblCities>(entity =>
        {
            entity.HasKey(e => e.CityId);

            entity.ToTable("tblCities");

            entity.Property(e => e.CityId).HasColumnName("CityID");

            entity.Property(e => e.CityName)
                  .IsRequired()
                  .HasMaxLength(20)
                  .IsUnicode(false);
        });

        modelBuilder.Entity<TblEmployee>(entity =>
        {
            entity.HasKey(e => e.EmployeeId);

            entity.ToTable("tblEmployee");

            entity.Property(e => e.EmployeeId).HasColumnName("EmployeeID");

            entity.Property(e => e.City)
                  .IsRequired()
                  .HasMaxLength(20)
                  .IsUnicode(false);

            entity.Property(e => e.Department)
                  .IsRequired()
                  .HasMaxLength(20)
                  .IsUnicode(false);

            entity.Property(e => e.Gender)
                  .IsRequired()
                  .HasMaxLength(6)
                  .IsUnicode(false);

            entity.Property(e => e.Name)
                  .IsRequired()
                  .HasMaxLength(20)
                  .IsUnicode(false);
        });
      } 
   }
}

Итак, в соответствии с инструкциями, я прокомментировал метод OnConfiguring выше, где я делалжесткое кодирование.

Я добавил в файл appsettings.json:

{
  "Logging": {
    "LogLevel": {
      "Default": "Warning"
   }
  },
  "ConnectionStrings": {
    "DBAngular5NetcoreEFDatabase": "Server=(localdb)\\mssqllocaldb;Database=DBAngular5NetcoreEF;Trusted_Connection=True;MultipleActiveResultSets=true"
  },
  "AllowedHosts": "*"
}

Я добавил в свой файл Startup.cs - ConfigureServices:

using Angular5NetcoreEF.Models;
using Microsoft.EntityFrameworkCore;

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);

    // In production, the Angular files will be served from this directory.
    services.AddSpaStaticFiles(configuration =>
    {
        configuration.RootPath = "ClientApp/dist";
    });

    // I added this.
    services.AddDbContext<DBAngular5NetcoreEFContext>(options => options.UseSqlServer(Configuration.GetConnectionString("DBAngular5NetcoreEFDatabase")));
}

Ответы [ 2 ]

0 голосов
/ 20 декабря 2018

проблема, с которой вы сталкиваетесь, заключается в том, что вы не используете шаблон внедрения зависимостей.Во-первых, вам нужно вставить DbContext из сервисов посредством внедрения зависимостей конструктором с помощью

public class EmployeeDataAccessLayer 
{
   private DBAngular5NetcoreEFContext _db;

   public EmployeeDataAccessLayer(DBAngular5NetcoreEFContext db)
   {
      _db = db;
   }
}

Во-вторых, все ссылки также должны быть внедрены, поэтому на каждом уровне приложения для каждого класса, такого как ваш EmployeeDataAccessLayerСначала вы должны: Зарегистрируйте его с помощью внедрения зависимостей, используя в Startup.cs -> ConfigureServices(): то есть services.AddScoped<EmployeeDataAccessLayer>();, а затем внедрите его в конструктор контроллера, как в случае выше.

Вы можете узнать о внедрении зависимостей и примерах областей действия (Scoped, Transient, Singleton ...) из ie Doc

В целях безопасности в текущем сценарии для проверки наличия ненастроенного контекста вы можете сделать что-то вроде:

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        if (!optionsBuilder.IsConfigured)
        {
             throw new Exception("Context not configured");
        }
    }

А также "временное отключение" пустого конструктора

0 голосов
/ 20 декабря 2018

Вы не должны создавать новый экземпляр DBAngular5NetcoreEFContext внутри EmplyeeDataAccessLayer.Вместо этого вы должны ввести его.

Вам также необходимо зарегистрировать EmployeeDataAccessLayer в контейнере DI и вставить его в EmployeeController.

По сути, вы позволяете контейнеру DI разрешать зависимости для вас.

public class Startup
{
    ...
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddDbContext<DBAngular5NetcoreEFContext>
            (options => options.UseSqlServer(Configuration.GetConnectionString("DBAngular5NetcoreEFDatabase")));

        services.AddScoped<EmployeeDataAccessLayer>();
        ...        
    }
    ...
}

public class EmployeeController : Controller
{
    private readonly EmployeeDataAccessLayer objemployee;

    public EmployeeController(EmployeeDataAccessLayer employeeDataAccessLayer)
    {
        objemployee = employeeDataAccessLayer;
    }
}

public class EmployeeDataAccessLayer
{
    private readonly DBAngular5NetcoreEFContext _db;

    public EmployeeDataAccessLayer(DBAngular5NetcoreEFContext db)
    {
        _db = db;
    }
    ...
}

Другая мысль заключается в использовании interface вместо конкретной реализации.Это облегчит вашу жизнь, когда вы начнете тестировать модули

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...