Как правильно использовать DbContext в разных проектах в одном решении? - PullRequest
0 голосов
/ 28 февраля 2020

У меня есть. Net Базовое решение, которое состоит из 3 проектов, как показано ниже:

  1. Common: (Все данные EF, миграции, модель, DbContext)
  2. WebApi: (Оставьте api, используя DbContext из Common)
  3. Работник: (Фоновые службы, которые нацелены на использование DbContext из Common)

Я хотел разместить все свои EF logi c и DbContext в Распространенный и потребляющий это от моих двух других проектов. WebApi работает нормально, но я не смог использовать его из моих сервисов, размещенных в проекте Worker. Есть 4 фоновых работника, и всем им требуется доступ к базе данных, поэтому я хотел получить доступ к своему DbContext внутри них.

Итак, как правильно повторно использовать DbContext в нескольких проектах. Можно считать, что все службы должны иметь доступ к некоторым общим таблицам. Поэтому изоляция таблиц с помощью различных Dbcontexts не подходит для меня.

Это мой Startup.cs в WebApi:

services.AddDbContext<DataContext>(options => options
        .UseNpgsql(Configuration.GetConnectionString("DefaultConnection")));

Это моя программа .cs в Worker:

services.AddDbContext<DataContext>(options => options
        .UseNpgsql(Configuration.GetConnectionString("DefaultConnection")));

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

Ответы [ 3 ]

1 голос
/ 28 февраля 2020

Если вы просто хотите сослаться на DbContext в вашем Web API + Background Workers, тогда я не понимаю, в чем проблема: просто ссылайтесь на общий проект из ваших рабочих проектов. Судя по вашему сообщению, проблема заключается в том, что внедрение службы, которое вы успешно используете в Web API, не работает с фоновыми рабочими службами. (Предполагая Windows Службы?)

Вместо этого начните с более простого сценария. Инициируйте DbContext внутри службы, когда он используется, а не вводите его.

Т.е.

using(var context = new DataContext("DefaultConnection"))
{
    // ...
}

Ваша конфигурация строки подключения должна идентифицировать NPG SQL в качестве поставщика, если эта конфигурация все настроено в вашей конфигурации служб, тогда DBContext должен быть в состоянии настроить по имени строки подключения. Если это сработает, то, вероятно, будет другой механизм для инъекций. Из того, что я мог быстро найти, кажется, что примеры использовали шаблон локатора службы для разрешения зависимостей, я не знаю, есть ли лучшие варианты в наши дни для Windows Служб.

Если внедрение не действительно вариант и вам придется прибегнуть к реализациям, подобным локаторам служб, тогда я, вероятно, рассмотрю что-то вроде шаблона внедрения Lazy Property, который я использовал в прошлом:

public class WorkerService
{
    private readonly IContainer _container = null;

    public WorkerService(IContainer container)
    {
        _container = container ?? throw new ArgumentNullException("container");
    }

    private IDataContextFactory _contextFactory = null;
    public IDataContextFactory ContextFactory
    {
        get { return _contextFactory ?? (_contextFactory = _container.Resolve<IDataContextFactory>()); }
        set { _contextFactory = value; }
    }

    public void Execute()
    {
         using(var context = ContextFactory.Create()) // returns a DataContext.
         {
             // do stuff.
         }
    }

}

Где IContainer представляет интерфейс контракта для вашего данная структура DI. (Unity, Autofa c, et c.)

Альтернативно, единица работы для определения объема DbContext. Поскольку экземпляр службы будет работать долго, мы не хотим внедрять или разрешать DbContext, а скорее фабрику контекста, которую мы можем использовать для получения инициализированного DbContext, который можно использовать при утилизации. Обычно с веб-запросами экземпляр ограничивается запросом и удаляется контейнером в конце запроса. С помощью сервиса мы хотим обеспечить регулярную утилизацию DbContext. DI может быть настроен так, чтобы возвращались временные экземпляры контекста, но эти экземпляры должны быть расположены, что означает, что он не подходит для внедрения конструктора, а скорее через локатор службы. Если бы один экземпляр DbContext использовался и внедрялся в конструктор службы, он работал бы до тех пор, пока служба не остановилась, и увидел бы, что DbContext становится все медленнее и медленнее с течением времени из-за отслеживаемых объектов.

1 голос
/ 28 февраля 2020

Я думаю, что вы здесь немного запутались. То, что вы хотите использовать повторно, это код DbContext + все логи EF c. Вы не хотите (не можете) повторно использовать один и тот же экземпляр DbContext в разных проектах (приложениях).

Таким образом, чтобы повторно использовать код, вам просто нужно поместить весь ваш Model + DBContext в проект. Затем в других проектах вы можете добавить ссылку на него. И начни его использовать.

0 голосов
/ 28 февраля 2020

Удалите все AddDbContext из Startup.cs / Program.cs.

Вместо этого поместите строку соединения DbContext в общий проект.

Создайте несколько CRUD в общем проекте. Тогда все другие проекты могут использовать CRUD для Common, который подключен к тому же DbContext.

...