Один DbContext на всё приложение

186
17 августа 2018, 17:40

Во многих мануалах в интернете и в учебнике Фримена для Identity создавался отдельный контекст БД (его даже наследовать надо от специального IdentityDbContext).
Я так и пытался сделать в своём проекте, а потом столкнулся со сложностями связывания. Я задал вопросы тут (ruSO и enSO), но решения не последовало.

В связи с этим у меня возник другой вопрос: на сколько нормальной считается практика использовать один контекст БД для всего приложения? (Приложение по функционалу представляет из себя что-то на подобии форума с постами, комментариями и модерацией).

То есть, на сколько нормальным будет считаться подобный один контекст на всё приложение:

public class AppContext : IdentityDbContext<ApplicationUser, ApplicationRole, int>
{
    public AppContext(DbContextOptions<AppContext> options) : base(options) { }
    public DbSet<Forum> Forums { get; set; }
    public DbSet<Post> Posts { get; set; }
    public DbSet<Comment> Comments { get; set; }
    public DbSet<Attachment> Attachments { get; set; }
    //прочие таблицы         
    protected override void OnModelCreating(ModelBuilder builder)
    {
        builder.Entity<Forum>(ConfigureForum);             // forum -> [has many] -> posts
        builder.Entity<Post>(ConfigurePost);               // post -> [has one] -> applicationUser; post -> [has many] -> comments
        builder.Entity<Comment>(ConfigureComment);         // comment -> [has one] -> applicationUser; comment -> [has one] -> parent_comment
        builder.Entity<Attachment>(ConfigureAttachment);   
        builder.Entity<PostAttachment>(ConfugurePostAttachment);
        builder.Entity<CommentAttachment>(ConfugureCommentAttachment);
    }
    // Описание методов конфигурации
}

Каждый пост и комментарий имеет автора в лице ApplicationUser, что и вызывает сложности при разделении контекста.

Answer 1

По поводу модульности. Во многих приложениях есть такий принцип, что всё приоложение разделено на независимые модули, которые могут подключаться и отключаться. Каждый модуль реализует какие-то функциональные возможности. Например, на этой картинке

вкладки session, bans, admins, players, manage server и чат - представляют собой отдельные модули, которые могут быть при желании отключены.

Это очень удобно, так как позволяет разбить всю функциональность приложения на небольшие участки, которые легче развивать, поддерживать и заменять. Это таже может быть основой для добавления аддонов (расширений) в приложение. Это касается не только десктоп приложений, но и любых других, например, CMS Orchard, WordPress и тд. Собственно, разделение на модули снижает сложность приложения и даже может увеличить его надежность. Если рассуждать дальше, то для серверных приложений следующий шаг после модульности - переход к микросервисам

Конечно, нужно понимать, что если вы собираетесь писать модульное приложение, то это потребует дополнительных усилий с вашей стороны, так как вам надо будет решить много вопросов по загрузке модулей, их сообщению, необходимости изоляции модулей и тд. Потому писать hello world модульным смысла не имеет.

Что касается контекста данных. Как я уже сказал, верного рецепта нет. Есть только те возможности, что вас устраивают. Если вы хотите сохранить модуль авторизации полностью отделенным от всего остального, то тогда да, вам луше вести 2 контекста данных, и ваша основная логика должна хранить только ту часть информации о юзерах, что для неё требуется. То есть, например, физ адрес юзера, его прдпочтения в еде, его подписки на рассылку - это все та инфа, что не касается авторизации, и её вы можете хранить в основном контексте данных. А вот логин/хеш пароля, счетчик попыток входа, и тд - это в контексте авторизции. Тогда ваши контексты никак не должны пересекаться. (Почитайте также про более широкое понятие контекста - DDD bounded context) И чтобы получить, например, таблицу [логин юзера - подписка] вам придется делать 2 запроса. Сначала получить подписки в виде [ид юзера - подписка] из основного контекста, а потом получить логины юзеров по айдишникам через модуль авторизации [ид юзера - логин юзера], и в памяти уже объединять результаты. Поначалу это кажется излишним, но это сыграет роль, если данные авторизации понадобится хранить в отдельной БД или придется выделить авторизацию в отдельный микросервис, или модуль авторизации надо будет переиспользовать в других проектах. Основной посыл тут - если разделить авторизацию и основную логику, то изменение авторизации не затронет никак основную логику.

Однако, если вы делаете учебный проект, где вы напишете авторизацию 1 раз и никогда уже не будете менять, где вы сделаете контекст данных 1 раз и больше он меняться не будет, где вы не предполагаете никакой модульности и изоляции модулей друг от друга, то тогда разделение контекста данных на 2 вам не даст никакой выгоды, но принесет проблем при поддержке и развитии приложения (с теми же миграциями, например).

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

READ ALSO
Установка monodevelop-database ubuntu

Установка monodevelop-database ubuntu

Все вышеперечисленные пакеты установились без проблем, кроме monodevelop-database

132
Узнать размера файла по условию

Узнать размера файла по условию

Нужно в цикле определять размер файла, и если он меньше чем в условии то удалять его путь из коллекции

167
Удаление изображений

Удаление изображений

Как в WPF удалить фотки из кэша? Потому что потом я не могу их редактировать, удалятьЕсли я хоть раз их загружу в программу, то потом из программы...

144
строка подключения mysql ado.net

строка подключения mysql ado.net

вот тут и возникли проблемы, пробовал делать вот так:

130