Внедрение строки подключения из файла конфигурации в EF Core DbContext - PullRequest
0 голосов
/ 29 марта 2019

Мне нужно внедрить зависимость в мой класс DbContext для моего проекта. Я пытаюсь сделать это так, как следует из «Чистой архитектуры».

Мне нужно иметь возможность использовать пустой конструктор DbContext и по-прежнему ссылаться на строку подключения из файла конфигурации.

Я использую этот универсальный репозиторий и внедряю его в сервисы. Это определено на прикладном уровне.

     public class GenericRepository<C, T> : IGenericRepository<C, T> where T : class where C : DbContext, new()
     {
        private DbContext _entities = new C();
     }

В моем классе EF Core Context (определенном на уровне постоянства) у меня есть это:

   public partial class MyContext : DbContext
   {
       private IConnectionStringProvider _connectionStringProvider;  

        public virtual DbSet<MyEntity> { get; set; }

        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            if (!optionsBuilder.IsConfigured)
            {  
                optionsBuilder.UseSqlServer(_connectionStringProvider.GetConnectionString());
            }
        }
    }

У меня также есть реализация для IConnectionStringProvider, определенная на уровне постоянства. Я хочу, чтобы эта реализация была легко заменяемой в случае необходимости. На данный момент он читает из App.config и использует пакет nuget ConfigurationManager. Но это может измениться в будущем, поэтому его нужно легко заменить.

IConnectionStringProvider определен на прикладном уровне:

 public interface IConnectionStringProvider
 {
     string GetConnectionString();
 }

В моем уровне Presentation у меня есть проект ASP.NET Core MVC. В StartUp.cs я использую стандартный способ внедрения dbContext в мои контроллеры:

services.AddDbContext<ContractsWorkloadContext>();

Я могу заставить это работать нормально, если переопределю OnModelCreatingMethod следующим образом.

 protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
 {
     if (!optionsBuilder.IsConfigured)
     {
         _connectionStringProvider = new ConnectionStringProvider();
         optionsBuilder.UseSqlServer(ConnectionStringProvider.GetConnectionString());
     }
 }

Этот метод позволяет мне использовать значения строки подключения из конфигурации с пустым экземпляром конструктора контекста, который необходим для его работы с моим общим репозиторием, а также все еще иметь возможность использовать конструктор с параметром DbContextOptionsBuilder.

Моя единственная проблема, которую предстоит решить, - это как добиться этого, чтобы контекст не зависел от реализации.

Я попытался внедрить свойство Autofac, зарегистрировав интерфейс и реализацию IConnectionStringProvider, а также зарегистрировав класс Context со свойствами "Autowired". Но свойство всегда равно нулю.

И да, я понимаю, что выше это поле, а не собственность. Я пытался изменить класс контекста, чтобы иметь свойство вместо поля. Я попытался даже создать метод для установки поля и использовать метод инъекции с автофаком. Но свойство / поле всегда равно нулю в каждом случае.

 builder.RegisterType<ConnectionStringProvider>().As<IConnectionStringProvider>()();
 builder.RegisterType<MyContext>().PropertiesAutowired();

И

 builder.RegisterType<ContractsWorkloadContext>().OnActivated(e =>
 {
     var provider = e.Context.Resolve<IConnectionStringProvider>();
     e.Instance.SetConnectionstringProvider(provider);
 });

В итоге мне нужно:

  1. Вставить строку подключения в контекст
  2. Разрешить создание пустого экземпляра конструктора
  3. Поддерживать дизайн "Чистая архитектура"

Любая помощь здесь будет оценена.

Спасибо.

1 Ответ

0 голосов
/ 29 марта 2019

В итоге я создал статическую ссылку на строку подключения, а затем свойство только для чтения в контексте, которое возвращает это значение.

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

Кроме того, добавив свойство readonly, которое возвращает строку статических соединений, я могу использовать универсальный репозиторий, который использует new () и по-прежнему получать строку подключения из файла конфигурации.

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

DbContext

Статическое значение задается реализацией провайдера в файле StartUp.cs на уровне представления.

Set Static Value

Это определенно работает ... Но если есть лучший способ, то я все уши ...:)

...