Что не так с ASP.NET Identity в Onion архитектуре?

Решил что для меня настало время пробовать крутые вещи как Onion архитектура Repository+UnitOfWork но мне довольно сильно понравилась ASP.NET Identity которую я бы хотел совместить с такой архитектурой приложения. Примеры которые нашлись в сети мне не очень понравились. К примеру metanit.com/sharp/mvc5/23.10.php тут полностью нарушена архитектура слоёв, а именно:
-в BLL слой подключен EntityFramework + Identity.EntityFramework
-в DAL слое наблюдается куча бизнес логики в виде ApplicationRoleManager и ApplicationUserManager
и тд...
Поэтому было решено сделать свой велосипед. Для начала я взял за пример проект который генерируется при создании ASP.NET MVC с уже включенной Identity и решил повторить его функционал при этом разнеся на 3 слоя.
Вот что вышло:
https://github.com/dmitrievMV/OnionArchitectureWit...

В DAL:
- Сущности.
- Контекст EF
- Repository+UnitOfWork
- UserStore
Все реализации в собрке закрыты кроме UnitOfWork и UserStore. UserStore принимает в конструктор UOW и работает с репозиториями. Наружу смотрят только интерфейсы. Структура БД полностью повторяет пример от мелкомягких кроме того что основные ключи int.
В BLL:
-ApplicationUserManager
В WEB
-ApplicationSignInManager

Собственно помогите пожалуйста, потратьте немного времени, просто проинспектируйте код. Ответьте на пару вопросов:
-Правильно ли я реализовал Repository + UnitOfWork
-Правильно ли реализовано Dispose
-В каком слое по вашему должен находится ApplicationSignInManager, ведь он использует OWIN и работает с ApplicationUserManager
-Ввиду того что о базе и орм не знает ни один слой кроме DAL я решил вынести connectionString в константу, это нормальный подход?
-Есть смысл вынести сущности в отдельный проект и отделить их от аннотаций для бд?
-В примере в owin контекст засовывают ef контекст вот таким образом app.CreatePerOwinContext(ApplicationDbContext.Create); насколько это оправдано и стоит ли так делать?
-В реализации UserStore для EF очень странно ведут себя с dispose и у меня ощущения что некоторые данные висят в памяти постоянно, так ли это?
-Насколько вообще оправдан такой велосипед?
  • Вопрос задан
  • 968 просмотров
Решения вопроса 1
Valeriy1991
@Valeriy1991
Разработчик .NET C# (ASP.NET MVC) в Alfa-B, Moscow
Добрый день!

Правильно ли я реализовал Repository + UnitOfWork

Ну, насколько я знаю, существует множество реализаций UnitOfWork + Repository, и каждая их них обладает своими достоинствами и недостатками. У Вас все выглядит достаточно работоспособно и юнит-тестируемо.

Правильно ли реализовано Dispose

В принципе, да. Только вот private fields на то и private, чтобы их инкапсулировать. Считаю очень неправильным, что у вас переменная disposed имеет модификатор public. Еще видел где-то в сети, что рекомендуют явно присваивать в переменную db значение null после вызова db.Dispose():
if (_db != null)
{
    _db.Dispose();
    _db = null;
}

Не хочу показаться навязчивым или развивать тему холивара, но именовать private field через символ "_" в начале имени, на мой взгляд, все же удобнее. Т.е. вместо private DbContext db лучше написать private DbContext _db. Как мне кажется, визуально такой код другим людям читать легче.

В каком слое по вашему должен находится ApplicationSignInManager, ведь он использует OWIN и работает с ApplicationUserManager

Зависит от сложности Вашего приложения. Может быть такая ситуация, что MVC-приложений несколько, но они должны использовать один механизм авторизации/аутентификации. Тогда компонент ApplicationSignInManager можно вынести в отдельный проект. Если такой необходимости нет, то, на мой взгляд, можно спокойно оставить его в клиенте (MVC-app).

Ввиду того что о базе и орм не знает ни один слой кроме DAL я решил вынести connectionString в константу, это нормальный подход?

Нет. Строки подключения к БД лучше всего хранить как настроечные параметры. Для ASP.NET 5 - в web.config, например. Для ASP.NET Core - например, в файле appsettings.json.

Есть смысл вынести сущности в отдельный проект и отделить их от аннотаций для бд?

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


В примере в owin контекст засовывают ef контекст вот таким образом app.CreatePerOwinContext(ApplicationDbContext.Create); насколько это оправдано и стоит ли так делать?
В реализации UserStore для EF очень странно ведут себя с dispose и у меня ощущения что некоторые данные висят в памяти постоянно, так ли это?

Вот тут не подскажу. Буду рад также услышать компетентное мнение.

Насколько вообще оправдан такой велосипед?

Какой именно велосипед? :) Если собственная реализация всяких ***Store, то думаю, да, потому что иначе их развязать и расположить в разных слоях не получится (сам мучился этим вопросом, и в итоге, потратив тонну времени, последовал совету делать свои реализации ***Store, чтобы делать архитектуру более модульной и упрощающей юнит-тестирование).

В свое время мне очень помогла вот эта серия статей (из 4 частей): techbrij.com/generic-repository-unit-of-work-entit...
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы