powered by simpleCommunicator - 2.0.38     © 2025 Programmizd 02
Форумы / ASP.NET [игнор отключен] [закрыт для гостей] / Иньекция DbContext
25 сообщений из 98, страница 2 из 4
Иньекция DbContext
    #40015623
Фотография hVostt
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
fkthat
hVostt
fkthat,

Вообще, за SingleOrDefault по айдишнику нужно бить по пальцам :)
Всегда нужно использовать Find(), прям железно.

Почему?


Find() берёт из кеша :)


fkthat
1) Сервис А использует контекст и вызывает сервис Б, сервис Б тоже использует контекст, но не знает (и не должен ничего знать) про сервис А, т.к. инкапсуляция, single responsibility и все такое. И, понятно, что он тем более не знает что там перед ним сервис А с контекстом натворил. Запросто можно нарваться на какие-нибудь неожиданности.


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

fkthat
2) Сервис А использует контекст и вызывает сервис Б. Сервис Б использует контекст и сохраняет свои изменения. Если сервис А перед вызовом Б внес свои изменения и еще не сохранял, то сервис Б сам того не ведая сохранит и их тоже и это как-то некрасиво.


Да, всё верно, если другой сервис вызвал SaveChanges контекста, это сохранит все изменения контекста.

И это, разумеется, правильно. Ибо ты сохраняешь состояние.

То, как ты описал, выглядит как независимые изменения, в таком случае ты тупо идёшь против самой концепции контекста. Как бы идёшь в разрез роли компонента в проекте. Ибо это UOW, а он не может быть точечным и независимым в рамках всей операции (читай, запроса).

И с другой стороны, если SaveChanges у тебя вызывается на разных уровнях, это очень кривая архитектура. Сохранение должно быть строго в одном слое.
...
Рейтинг: 0 / 0
Иньекция DbContext
    #40015695
fkthat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
hVostt,

Да лично я-то никогда на практике со scoped data context проблем не имел, но просто вижу возможность их поимения. Потому что, повторюсь, scoped это по сути нечто глобальное, к чему имееет доступ все что только можно. А что-то глобальное это всегда возможность выстрелить себе в ногу. Это-то мне и не нравится.

Вот, смотри, такой, допустим, воображаемый сценарий.

1) Сервис А добавляет в контекст запись о покупке
2) Сервис А вызывает сервис Б чтобы вычислить НДС
3) Сервис А добавляет НДС в запись о покупке
4) Сервис А сохраняет изменения через SaveChange

Выглядит все нормально. Но вот. Я как разработчик сервиса А не знаю, да и знать не хочу как внутри устроен сервис Б. И поэтому я в душе не ведаю, что сервис Б для чего-то и сам вызывает SaveChanges (кто его там знает, может он какой-то аудит вызовов в базу пишет) - и он в этом вполне прав, потому что его тоже не должно волновать, что и как я перед его вызовом делал. И при таком сценарии между п.2 и п.3 в БД окажется некорректная запись (с ценой, но без НДС), которую, между прочим, какой-то другой запрос может прочитать, т.к. другой запрос будет в другом скоупе и у него будет "чистый" датаконтекст.

С т.з. правильного использования UoW я пока вижу только такой вариант, чтобы над всеми этими сервисами ставить какой-то сервис-оркестратор, который будет заниматься только тем, что вызывать нужные сервисы, а потом одним махом делать общий "коммит" в виде вызова SaveChanges.
...
Рейтинг: 0 / 0
Иньекция DbContext
    #40015696
fkthat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
hVostt
И это, разумеется, правильно. Ибо ты сохраняешь состояние.

Чего же тут правильного, если я вызывая какой-то сервис, который писал вообще не я, должен всегда думать: "а не сохранит ли он мне то моё, что я еще пока что сохранять еще не хочу". Это вообще нарушение всех принципов модульности и инкапсуляции.
...
Рейтинг: 0 / 0
Иньекция DbContext
    #40015837
Фотография hVostt
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
fkthat
Вот, смотри, такой, допустим, воображаемый сценарий.

1) Сервис А добавляет в контекст запись о покупке
2) Сервис А вызывает сервис Б чтобы вычислить НДС
3) Сервис А добавляет НДС в запись о покупке
4) Сервис А сохраняет изменения через SaveChange


Проблема в п.4
Сервис А не должен сохранять изменения :)


fkthat
Выглядит все нормально. Но вот. Я как разработчик сервиса А не знаю, да и знать не хочу как внутри устроен сервис Б. И поэтому я в душе не ведаю, что сервис Б для чего-то и сам вызывает SaveChanges


И поэтому ни Б, ни В, ни кто-то ещё не должен отвечать за сохранение. Это логика подготовки изменений. Конечное решение принимается на самом верхнем уровне.

Ибо.

Если ты последовательно выполняешь сервисы А, Б, В... и т.д., и хочешь сохранить тогда и только тогда, когда все сервисы корректно отработали, ты хрен это сделаешь, если каждый сервис будет самовольно что-то там сохранять (совсем страх потеряли..)

Подумай над этим :)

Смысл UOW в том, что ты только в одном месте принимаешь конечно решение.
И для тестирования хорошо.

А ещё инетресней всё становится, когда ты переписал всё в функциональном стиле, где вообще за эффекты в виде сохранения чего-то там куда-то внутри сервисных функций, бьют ногами :)
...
Рейтинг: 0 / 0
Иньекция DbContext
    #40015839
Фотография hVostt
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
fkthat
над всеми этими сервисами ставить какой-то сервис-оркестратор, который будет заниматься только тем, что вызывать нужные сервисы


Ну вообще, задача разработки не усложнять, а упрощать.
Сервис-оркестратор у тебя уже из коробки есть.

Это контроллер.
...
Рейтинг: 0 / 0
Иньекция DbContext
    #40015840
Фотография hVostt
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
fkthat
hVostt
И это, разумеется, правильно. Ибо ты сохраняешь состояние.

Чего же тут правильного, если я вызывая какой-то сервис, который писал вообще не я, должен всегда думать: "а не сохранит ли он мне то моё, что я еще пока что сохранять еще не хочу". Это вообще нарушение всех принципов модульности и инкапсуляции.


Ну и чем поможет transient здесь? Ну потеряешь ты вообще всякий контроль, чем лучше?
Какой-то левый сервис что-то там сохранит, а тебе это не надо, если на втором шаге условие не выполняется.
Что делать?
Ничего, грызть локоть.

И зачем такое нужно? :)
...
Рейтинг: 0 / 0
Иньекция DbContext
    #40015885
fkthat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
hVostt
Ну и чем поможет transient здесь? Ну потеряешь ты вообще всякий контроль, чем лучше?

Ничего я не потяряю. Мой сервис будет работать со своим экземпляром контекстьа. Другой сервис будет работать со своим. Это как локальные переменные vs глобальные - меняя локальную переменную я гарантированно ни на что что за пределами её видимости не повлияю, поэтом я не парюсь ни о том можно ли мне и как её менять и так же не парюсь о том, что кто-то без моего ведома её поменяет.

hVostt
Какой-то левый сервис что-то там сохранит,

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

Это еще очень напоминает известную замороку со вложенными транзакциями в SQL. Там из-за этого, если ты хочешь внутри SP делать транзакцию приходится ставить проверки не находишься ли ты уже внутри транзакции. По крайней мере, когда-то это было так.
...
Рейтинг: 0 / 0
Иньекция DbContext
    #40015929
Фотография hVostt
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
fkthat
Ничего я не потяряю. Мой сервис будет работать со своим экземпляром контекстьа. Другой сервис будет работать со своим. Это как локальные переменные vs глобальные - меняя локальную переменную я гарантированно ни на что что за пределами её видимости не повлияю, поэтом я не парюсь ни о том можно ли мне и как её менять и так же не парюсь о том, что кто-то без моего ведома её поменяет.


Не совсем понял, нафига тебе это.

Давай абстрактно, вот есть POST-запрос.
В рамках запроса у тебя может выполняться ряд операций разных сервисов.

С точки зрения интерфейса, это _единая операция_, клиенту как бы плевать сколько у тебя там сервисов и вообще на все твои 100500 слоёв и сервисов положить.

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

Как бы DbContext в скоупе идеально ложится на эту концепцию. На этом принципе выполнено огромное дохренища проектов, и первый раз слышу, чтобы кого-то это не устраивало :))
...
Рейтинг: 0 / 0
Иньекция DbContext
    #40015930
Фотография hVostt
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
fkthat
Это еще очень напоминает известную замороку со вложенными транзакциями в SQL. Там из-за этого, если ты хочешь внутри SP делать транзакцию приходится ставить проверки не находишься ли ты уже внутри транзакции. По крайней мере, когда-то это было так.


Ну так вот scoped контекст эту проблему решает.
...
Рейтинг: 0 / 0
Иньекция DbContext
    #40016024
fkthat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
hVostt
Как бы DbContext в скоупе идеально ложится на эту концепцию. На этом принципе выполнено огромное дохренища проектов, и первый раз слышу, чтобы кого-то это не устраивало :))

Ну и где там SaveChanges происходит? В конце вызова контроллера? Смахивает на костыль какой-то.
...
Рейтинг: 0 / 0
Иньекция DbContext
    #40016027
fkthat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
hVostt
fkthat
Это еще очень напоминает известную замороку со вложенными транзакциями в SQL. Там из-за этого, если ты хочешь внутри SP делать транзакцию приходится ставить проверки не находишься ли ты уже внутри транзакции. По крайней мере, когда-то это было так.


Ну так вот scoped контекст эту проблему решает.

Как решает?
...
Рейтинг: 0 / 0
Иньекция DbContext
    #40016273
Фотография hVostt
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
fkthat
hVostt
Как бы DbContext в скоупе идеально ложится на эту концепцию. На этом принципе выполнено огромное дохренища проектов, и первый раз слышу, чтобы кого-то это не устраивало :))

Ну и где там SaveChanges происходит? В конце вызова контроллера? Смахивает на костыль какой-то.


ну давай на примере:

Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
...Controller
{
    ...SomeAction(...)
    {
        _service1.Operation();
        _service2.Operation();
        _service3.Operation();
        return Ok(...);
    }
}



в _service1 ты что-то сохранил, а на _service2 у тебя что-то бахнет, значит мы вылетим из действия с искаверканными данными в БД (по бизнесу).

норм?

это не костыль, это большая увесистая грабля с гранатой на ручке.
...
Рейтинг: 0 / 0
Иньекция DbContext
    #40016274
Фотография hVostt
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
fkthat
hVostt
пропущено...


Ну так вот scoped контекст эту проблему решает.

Как решает?


DbContext это UOW.

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

Он не создан, чтобы тупо сейвить каждой изменение каждой фигни в проекте.
Это общее сохранение всей проделанной работы.
...
Рейтинг: 0 / 0
Иньекция DbContext
    #40016275
Фотография hVostt
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
fkthat,

Не, я могу конечно ошибаться в твоём случае.
Просто не понимаю пока сути проблемы..

Для меня transient DbContext это дичь :)
...
Рейтинг: 0 / 0
Иньекция DbContext
    #40016289
fkthat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
hVostt
Он не создан, чтобы тупо сейвить каждой изменение каждой фигни в проекте.
Это общее сохранение всей проделанной работы.

Вот. Теперь смотри. Я пишу компонент (сервис). Меня заботит только то, что этот сервис должен делать то, для чего он предназначен. Меня вообще не волнует и не должно волновать, кто, как, и в каком сценарии его использует. А теперь, откуда мне знать, что тот, кто его использует, или тот, кто использует того, кто его использует действительно сохраняет изменения.
...
Рейтинг: 0 / 0
Иньекция DbContext
    #40016290
fkthat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
hVostt

в _service1 ты что-то сохранил, а на _service2 у тебя что-то бахнет, значит мы вылетим из действия с искаверканными данными в БД (по бизнесу).

Если все три вызова должны быть одной транзакцией, значит их надо явно объединять в одну транзакцию. При твоем подходе, получается, что SaveChanges надо вообще куда-то в middleware выносить.

А, кстати, в твоем примере кода, если ничего-таки не бахнет, то кто SaveChanges будет делать?
...
Рейтинг: 0 / 0
Иньекция DbContext
    #40016397
Фотография hVostt
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
fkthat
Вот. Теперь смотри. Я пишу компонент (сервис). Меня заботит только то, что этот сервис должен делать то, для чего он предназначен. Меня вообще не волнует и не должно волновать, кто, как, и в каком сценарии его использует. А теперь, откуда мне знать, что тот, кто его использует, или тот, кто использует того, кто его использует действительно сохраняет изменения.


Это нарушение SRP.
DbContext это абстракция, а не работа с БД.

Одна из задач этой абстракции, это UOW.

Другими словами, ты говоришь, что твой сервис хочет работать с БД изолировано. Значит у него либо должен быть свой собственный личный DbContext, о котором никто ничего не знает, никто с ним больше не работает и вообще понятия не имеет, либо работать с БД напрямую.

fkthat
Если все три вызова должны быть одной транзакцией, значит их надо явно объединять в одну транзакцию. При твоем подходе, получается, что SaveChanges надо вообще куда-то в middleware выносить.

А, кстати, в твоем примере кода, если ничего-таки не бахнет, то кто SaveChanges будет делать?


Если в контексте ASP.NET, то контроллер.
...
Рейтинг: 0 / 0
Иньекция DbContext
    #40016398
Фотография hVostt
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
fkthat,

И всё же. Может есть реальный кейс, с которым ты столкнулся? Я просто за все свои множество лет опыта никогда таких проблем не ловил, наверное потому что воспринимают DbContext именно так, как он был задуман :)
...
Рейтинг: 0 / 0
Иньекция DbContext
    #40016406
fkthat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
hVostt
Если в контексте ASP.NET, то контроллер.

Т.е. инжектить DbContext в контроллер?
...
Рейтинг: 0 / 0
Иньекция DbContext
    #40016407
fkthat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
hVostt
Другими словами, ты говоришь, что твой сервис хочет работать с БД изолировано.

Да, потому что иначе он просто не реюзабельный, потому что становится зависимым от того, что снаружи него и как оно само работает.
...
Рейтинг: 0 / 0
Иньекция DbContext
    #40016408
fkthat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
hVostt
И всё же. Может есть реальный кейс, с которым ты столкнулся? Я просто за все свои множество лет опыта никогда таких проблем не ловил:)

Я тоже, но я же с самого начала и написал, "не ловил, но вижу возможность поймать". Впрочем, один раз что-то было, связанное с использованием Attach, впрочем, я не сторонник его использования, т.ч. это, скорее, исключение.
...
Рейтинг: 0 / 0
Иньекция DbContext
    #40016447
Фотография hVostt
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
fkthat
hVostt
Если в контексте ASP.NET, то контроллер.

Т.е. инжектить DbContext в контроллер?


Не совсем. Инжектить IUnitOfWork, который реализуется DbContext-ом.

fkthat
Да, потому что иначе он просто не реюзабельный, потому что становится зависимым от того, что снаружи него и как оно само работает.


Он и должен быть зависимым, DbContext это полная абстракция над хранилищем.

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


Ну если не ловил, зачем заморачиваться :)
Я вот не ловил, и даже не вижу проблем.

То о чём ты говоришь, выглядит примерно как:

— а что если вилкой в глаз тыкнуть, то что? давайте пробку на вилку оденем!
...
Рейтинг: 0 / 0
Иньекция DbContext
    #40016476
fkthat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
hVostt
Не совсем. Инжектить IUnitOfWork, который реализуется DbContext-ом.

Тоже плохо. Потому что IUnitOfWork это все равно DAL, а не BL.

fkthat
Он и должен быть зависимым.

Сервис, работа которого зависит от других сервисов, про которые он даже ничего не знает?

Отвлечемся вообще от БД и контекста. Допустим, у меня стек вызов сервисов А->B>C->D и оказывается, что поведение сервиса D зависитот того, что делал сервис A перед тем как вызвал B. Это уже не модульное приложение будет, а какая-то адова лапша.
...
Рейтинг: 0 / 0
Иньекция DbContext
    #40016477
Фотография Shocker.Pro
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ну вот смотри (как я расшифровываю подход Хвоста), само название Db Context делает его похожим на артефакты типа HttpContext и иже с ним. То есть вот у тебя запрос, он же скоуп, на него формируется HttpContext, DbContext еще какие-то контексты. Каждый из сервисов может модифицировать что-то в этом контексте, но закрытие и финальное решение по этим контекстам происходит именно в момент окончания работы со скоупом, ну в данном случае - это последние команды контроллера.
...
Рейтинг: 0 / 0
Иньекция DbContext
    #40016485
fkthat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Shocker.Pro
ну в данном случае - это последние команды контроллера.

А если он где-то в фильтре используется, или в middleware? Да и, как я уже писал, вызывать DAL прямо из контроллера это уже сама по себе хрень какая-то. А по-хорошему, если что-то шарится между разными компонентами, должно быть иммутабельно. Поскольку дбконтекст таковым не является, то от этого можно вполне ожидать какой-нибудь беды.
...
Рейтинг: 0 / 0
25 сообщений из 98, страница 2 из 4
Форумы / ASP.NET [игнор отключен] [закрыт для гостей] / Иньекция DbContext
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]