Arhn - архитектура программирования

Как поделиться DbCOntext в шаблоне многоуровневого репозитория. ASP.NET MVC

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

У меня есть n-уровневое приложение в asp .net mvc, в котором у меня есть:
Проект BOL (в котором есть классы EF, объект db и т. Д.),
Проект BLL (который имеет бизнес-логику),
чем у нас есть проект DAL (который имеет логику взаимодействия с базой данных и использует EF dbcontext из BOL).
И основной проект mvc, который включает контроллеры, представления и т. д.

Теперь, мы используем шаблон репозитория, у нас есть много репозиториев в BLL с их интерфейсами. А также у нас есть много репозиториев в DAL, но без интерфейсов. Но во всех этих репозиториях DAL есть один член DbContext, который создается в их конструкторах, поэтому каждый репозиторий DAL взаимодействует с отдельным экземпляром DbContext, который он создал.


В нашем основном проекте mvc мы использовали ninject для внедрения репозиториев BLL в конструкторы контроллеров (в области запроса). Теперь проблема, с которой мы сталкиваемся, заключается в том, что каждый репозиторий BLL имеет ссылки на один или несколько репозиториев DAL, а каждый из этих репозиториев DAL использует свой собственный отдельный DbCOntext. Это неправильно и плохо, поэтому я ищу способ поделиться одним DbCOntext во всех репозиториях DAL для каждого запроса (независимо от того, сколько репозиториев BLL вводит в мой контроллер, просто убедитесь, что создается и используется только один экземпляр DbContext по запросу). И удаляйте этот контекст после каждого запроса.

Один из способов, который я думал, заключался в том, чтобы не создавать DBcontext в конструкторе репозиториев DAL. Но имейте для этого вызов какого-нибудь метода (скажем, initiateDbContext), чем также добавьте этот метод в репозитории BLL, которые ничего не делают, кроме вызова метода smae своих репозиториев DAL. Вызовите этот метод для одного репозитория BLL в конструкторе контроллера, а затем получите метод для получения и установки контекстов базы данных во всех других репозиториях из первого репозитория. Но я знаю, что это плохой подход, во-первых, мы создаем DbContext в контроллере, который должен быть только в DAL, во-вторых, я добавляю методы create, get и set DbCOntext в DAL, а также в репозитории BLL, потому что мне нужно передать DbCOntext в BLL, который передаст это в репозитории DAL, с которыми он общается внутри. И это очень плохо.

Вот почему я прошу здесь любой хороший шаблон для достижения «ОДИН DBCONTEXT НА ЗАПРОС НА N-УРОВНЕ С ШАБЛОНОМ РЕПОЗИТОРИИ».


  • Случайное выделение слов жирным шрифтом не делает ваш вопрос более читабельным. 04.04.2016
  • @CodeCaster Я знаю, что мой вопрос не имеет большого смысла, но я ПЫТАЛСЯ выделить некоторые важные моменты, чтобы их было легко понять. Может, подскажете что-нибудь? 04.04.2016

Ответы:


1

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

04.04.2016
  • Имеет смысл, это означает, что я должен включить ninject в свой проект DAL, и все мои репозитории должны получать необходимые зависимости, репозитории BLL должны получать внедренный DAL, а репозитории DAL должны получать DbCOntext, введенный в них ninject. В этом есть смысл, но я никогда не использовал ninject в такой многоуровневой архитектуре. Что мне нужно в Google, чтобы получить информацию по этому поводу. Я имею в виду, что это за терминология. 04.04.2016
  • Первый удар для нескольких слоев ninject выглядит хорошей отправной точкой. Я не очень знаком с Ninject, но вижу, что он поддерживает модули. Это то, что я использую с Autofac, у каждого слоя есть собственный модуль, и он загружается слоем над ним. Делает разделение слоев очень простым. 04.04.2016
  • Хорошо, я изучаю это, и я должен сказать, что я новичок в этом, так что я могу наверстать упущенное, если возникнут новые затруднения. Спасибо за ваш ответ. Я отмечу как принятый, как только моя проблема будет решена. 04.04.2016
  • @DilipN на самом деле не нашел DI в вашем примере. 04.04.2016
  • @atika, не могли бы вы взглянуть на этот пример и дать мне шанс? Как я уже сказал, я новичок в этом типе инъекций, поэтому я довольно смущен. Для меня этот пример имеет смысл, просто проверьте его. Еще раз спасибо за вашу помощь. myseesharp.blogspot.com/2015/01/ 04.04.2016
  • @atika, спасибо, atika, сейчас я собираюсь реализовать это, похоже, это решит проблему. Я расскажу об этом здесь. И, конечно, примите ваш ответ. 04.04.2016
  • @atika, теперь я не понимаю, следует ли мне отмечать этот ответ как принятый или мой подробный ответ ниже, основанный на вашем ответе. Я опубликовал этот ответ, чтобы добавить подробности, которые мне пришлось изучить после вашего руководства, чтобы другие могли сэкономить время. Но вашим ответом было направление. Подскажите что делать: D 05.04.2016
  • Не уверен, что рекомендации SO рекомендуют в этом случае, но ваш ответ является более подробным, и я думаю, что можно отметить его как принятый. 05.04.2016

  • 2

    Основываясь на ответе @atika, я продолжил поиск и реализовал то, что он предложил (используя ninject / DI во всем приложении, а не только в одном основном проекте mvc), и это решило проблему: i Я отправляю этот ответ, чтобы добавить дополнительные сведения и некоторые дополнительные проблемы, с которыми я столкнулся, и мне нужно потратить время на поиск в Google, чтобы другие могли сэкономить время.


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

    Итак, проблема доходит до того, что если мы хотим использовать ninject или любой другой DI для привязки всех зависимостей со всех уровней / проектов, мы должны иметь ссылку на все эти уровни / проекты в нашем основном проекте mvc, так что мы можем связать зависимости в NinjectWebCommons, но это убьет всю цель n-уровневой архитектуры. Мы не хотим этого делать, мы хотим, чтобы наша иерархия поддерживалась, как в моем случае
    MainMVCProject-> BLL-> DLL-> DB
    Итак, < strong> я нашел очень полезную статью
    Ninject с N-уровневым приложением MVC - внедрить объект в бизнес-уровень. (Есть и другие подходы, один из них - создать проект только для привязок и добавить использование этого проекта для привязки всех зависимостей, но это звучит как излишняя инженерия и излишество)

    На основании чего я добавил следующий класс в свой уровень / проект BLL (после установки ninject в этом проекте и в проекте DAL), который имеет привязки для классов DLL.

    using BLL.Repositories;
    using BLL.RepositoryInterfaces;
    using Ninject.Modules;
    using Ninject.Web.Common;
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using DAL;
    using BOL;
    
    namespace BLL
    {
        public class LayerBindings : NinjectModule
        {
            public override void Load()
            {//add all references here like these
                Bind<AdDb>().ToSelf().InRequestScope();
                Bind<db_Entities>().ToSelf().InRequestScope().WithConstructorArgument("ConnectionString", BOL.CommonFunctionsBOL.ConnectionString);
            }
        }
    }
    

    Получение помощи от howto-ninject-part-1- основы, мне удалось многое сделать с помощью ninject, и я использовал многие из его функций.

    Теперь вы можете увидеть, что я добавил привязки проекта DLL в этот класс, которые были недоступны в основном проекте mvc. Теперь мне просто нужно загрузить эти привязки в основной нинджект. Теперь в файле NinjectWebCommons.cs я добавил следующие строки:

    //old bindings of BLL and local project.    
    kernel.Bind<IUserRepository>().To<UserRepository>().InRequestScope();
    //now here we bind other dependencies of DAL etc using class we added in BLL
    var modules = new List<INinjectModule>
    {
          new BLL.LayerBindings()
    };
    kernel.Load(modules);
    

    (В методе RegisterServices после локальных привязок и привязок объектов BLL.)

    После этого ninject начал работать во всех проектах, и я просто использовал инъекцию конструктора или в некоторых местах инъекции свойств, и все работало нормально.

    PS1: я также использовал инъекцию свойств * (я читал, что не рекомендуется использовать инъекции свойств, используйте их только там, где вы не можете использовать инъекции конструкторов.) * для частных свойств и их нужно было включить с помощью kernel.Settings.InjectNonPublic = true; строку в методе CreateKernel перед возвратом ядра.
    Теперь моя инъекция свойств работает и для частных свойств, например:

    [Ninject.Inject]
    private SomeDALObject db { get; set; }
    

    PS2: я также установил пакет nuget ninject.web.webapi для ninject для работы с webapis, а также нашел эту строку для получения объекта где угодно из ninjec t. (Я не знаю, хороший это способ или нет, но он возвращает полностью сконструированный объект, который я использовал, чем. Если кто-нибудь может прояснить или исправить меня, правильно ли это использовать или нет , это будет здорово.)

    ((TypeOfObjectYouWant)System.Web.Mvc.DependencyResolver.Current.GetService(typeof(TypeOfObjectYouWant))).DoSomething();
    

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

    05.04.2016
  • Спасибо, @Zia, упростило жизнь будущим посетителям. 15.04.2016

  • 3
  • не будет ли каждый репозиторий получит новый экземпляр базового репозитория, т.е. каждый репозиторий снова будет иметь другой контекст? Потому что каждый репозиторий будет унаследован от BaseRepository? 04.04.2016
  • @Dilip N Это не то, о чем просил OP, пожалуйста, пересмотрите свой ответ 04.04.2016
  • Новые материалы

    Коллекции публикаций по глубокому обучению
    Последние пару месяцев я создавал коллекции последних академических публикаций по различным подполям глубокого обучения в моем блоге https://amundtveit.com - эта публикация дает обзор 25..

    Представляем: Pepita
    Фреймворк JavaScript с открытым исходным кодом Я знаю, что недостатка в фреймворках JavaScript нет. Но я просто не мог остановиться. Я хотел написать что-то сам, со своими собственными..

    Советы по коду Laravel #2
    1-) Найти // You can specify the columns you need // in when you use the find method on a model User::find(‘id’, [‘email’,’name’]); // You can increment or decrement // a field in..

    Работа с временными рядами спутниковых изображений, часть 3 (аналитика данных)
    Анализ временных рядов спутниковых изображений для данных наблюдений за большой Землей (arXiv) Автор: Рольф Симоэс , Жильберто Камара , Жильберто Кейрос , Фелипе Соуза , Педро Р. Андраде ,..

    3 способа решить квадратное уравнение (3-й мой любимый) -
    1. Методом факторизации — 2. Используя квадратичную формулу — 3. Заполнив квадрат — Давайте поймем это, решив это простое уравнение: Мы пытаемся сделать LHS,..

    Создание VR-миров с A-Frame
    Виртуальная реальность (и дополненная реальность) стали главными модными терминами в образовательных технологиях. С недорогими VR-гарнитурами, такими как Google Cardboard , и использованием..

    Демистификация рекурсии
    КОДЕКС Демистификация рекурсии Упрощенная концепция ошеломляющей О чем весь этот шум? Рекурсия, кажется, единственная тема, от которой у каждого начинающего студента-информатика..


    © 2024 arhn.ru, Arhn - архитектура программирования