|
Иньекция DbContext
|
|||
---|---|---|---|
#18+
Стандартный паттерн использования DbContext в ASP.NET Core это его иньекция туда где он нужен. Сам DbContext при этом принято регистрировать как scoped (так по умолчанию). В принципе, не могу вспомнить, чтобы у меня случались какие-то проблемы с этим, но не оставляет ощущение, что в этом заложено что-то недоброе. Scoped компонент в ASP.NET Core это объект глобальный для всего HTTP request, т.е. со всеми возможными граблями глобального объекта (сторонние эффекты). Я однажды предложил вместо DbContext инжектить его фабрику, но у всех, разумеется, тут же полыхнуло, типа: "Еще наши прадеды инжектили DbContext, а ты тут собрался оскорбить их память и могилы обосс..ть". Вот мне и интересно узнать - кто-нибудь делает инъекцию DbContext не напрямую? ... |
|||
:
Нравится:
Не нравится:
|
|||
04.11.2020, 04:09 |
|
Иньекция DbContext
|
|||
---|---|---|---|
#18+
ну я пробовал раньше делать дженерик репо + uow и ощущал что это велик какой то. фабрика ты вроде как говоришт дело но тогда ты будешь отвечать за закрытие и обслуживание и где гарантиии что кто то из твоих прогеров не забудет про закрытие ручное( кто создал тот и мочит хороший тон) поэтому когда я пишу код лично я стараюсь прям в коде сделать ограничение по использованию чего либо чтоб след прогер минимально в ногу выстрелил, конечно эт не отменяет что можно удалить код. если мы говорим в концепции di то скоуп вполне себе модель. если так судить то у тебя все что в скоупе реквеста "глобальное" ... |
|||
:
Нравится:
Не нравится:
|
|||
04.11.2020, 21:08 |
|
Иньекция DbContext
|
|||
---|---|---|---|
#18+
handmadeFromRu тогда ты будешь отвечать за закрытие и обслуживание Нет, если фабрика будет работать через тот же DI, то при выходе из скоупа все что она насоздавала будет тоже диспозиться. В принципе, есть-то опция, чтобы регистрировать DbContext как transient, но на существующем проекте это как бы слишком уж глобаное изменение и делать его рисковано. ... |
|||
:
Нравится:
Не нравится:
|
|||
04.11.2020, 21:35 |
|
Иньекция DbContext
|
|||
---|---|---|---|
#18+
handmadeFromRu если так судить то у тебя все что в скоупе реквеста "глобальное" Да как бы нет, любой объект DI действительно принадлежить какому-либо скоупу, но ведь если он зареган как transient, то для каждой инъекции создается новый инстанс, так что никакой глобальности - каждый зависимый объект получит свой собственный экземпляр зависимости. ... |
|||
:
Нравится:
Не нравится:
|
|||
04.11.2020, 21:42 |
|
Иньекция DbContext
|
|||
---|---|---|---|
#18+
fkthat Нет, если фабрика будет работать через тот же DI, то при выходе из скоупа все что она насоздавала будет тоже диспозиться. В принципе, есть-то опция, чтобы регистрировать DbContext как transient, но на существующем проекте это как бы слишком уж глобаное изменение и делать его рисковано. где эт написано что оно высвободится то? что то новая инфа прям. ... |
|||
:
Нравится:
Не нравится:
|
|||
04.11.2020, 21:59 |
|
Иньекция DbContext
|
|||
---|---|---|---|
#18+
fkthat Да как бы нет, любой объект DI действительно принадлежить какому-либо скоупу, но ведь если он зареган как transient, то для каждой инъекции создается новый инстанс, так что никакой глобальности - каждый зависимый объект получит свой собственный экземпляр зависимости. опять же нет.. если ты регаешь как transient кто будет закрывать? скоуп как раз для этого. у меня вот куча сервисов, но transient очень малое колво в регистрации. прям почти все это скоупы + не много синглетоны ну вообще мало transient ... |
|||
:
Нравится:
Не нравится:
|
|||
04.11.2020, 22:01 |
|
Иньекция DbContext
|
|||
---|---|---|---|
#18+
handmadeFromRu где эт написано что оно высвободится то? что то новая инфа прям. Все что создается через ДиАй диспозится автоматически когда диспозится его скоуп. Это же испокон веков во всех контейнерах так. Сам проверь, убедись, если хочешь. И транзиент тоже. ... |
|||
:
Нравится:
Не нравится:
|
|||
04.11.2020, 22:56 |
|
Иньекция DbContext
|
|||
---|---|---|---|
#18+
handmadeFromRu опять же нет.. если ты регаешь как transient кто будет закрывать? Код: c# 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22.
... |
|||
:
Нравится:
Не нравится:
|
|||
04.11.2020, 23:10 |
|
Иньекция DbContext
|
|||
---|---|---|---|
#18+
handmadeFromRu у меня вот куча сервисов, но transient очень малое колво в регистрации. прям почти все это скоупы + не много синглетоны ну вообще мало transient Значит, ты просто делаешь все неправильно. Потому что скоуп совсем не для того, чтобы автоматически что-то там "закрывать". ... |
|||
:
Нравится:
Не нравится:
|
|||
04.11.2020, 23:12 |
|
Иньекция DbContext
|
|||
---|---|---|---|
#18+
fkthat Все что создается через ДиАй диспозится автоматически когда диспозится его скоуп. Это же испокон веков во всех контейнерах так. Сам проверь, убедись, если хочешь. И транзиент тоже. погоди ты говорил через фабрику а не di. если как к примеру в dryioc заюзать фитчу верни мне фабрику объектов да вызоветься а если ты нашлепал фабрику типо Код: c# 1. 2. 3. 4. 5. 6. 7.
то нет с transient был не прав. в голове шелкнуло наверное изза привычки dryioc , он подефлту Dispose интерфейсы не позволяет регистрировать как Transient. ... |
|||
:
Нравится:
Не нравится:
|
|||
05.11.2020, 00:01 |
|
Иньекция DbContext
|
|||
---|---|---|---|
#18+
fkthat Стандартный паттерн использования DbContext в ASP.NET Core это его иньекция туда где он нужен. Сам DbContext при этом принято регистрировать как scoped (так по умолчанию). В принципе, не могу вспомнить, чтобы у меня случались какие-то проблемы с этим, но не оставляет ощущение, что в этом заложено что-то недоброе. Scoped компонент в ASP.NET Core это объект глобальный для всего HTTP request, т.е. со всеми возможными граблями глобального объекта (сторонние эффекты). Я однажды предложил вместо DbContext инжектить его фабрику, но у всех, разумеется, тут же полыхнуло, типа: "Еще наши прадеды инжектили DbContext, а ты тут собрался оскорбить их память и могилы обосс..ть". Вот мне и интересно узнать - кто-нибудь делает инъекцию DbContext не напрямую? Ну вообще в рамках scoped (запроса) один экземпляр контекста -- это хорошо. Ибо транзакционность, ибо кеш первого уровня, и возможность на нескольких уровнях работать с полученным ентити. В одном месте получили, в другом записали. Если у тебя будет transient, ты огребёшь проблем и потерю в производительности. Другое дело, фабрика позволяет иметь более одного DbContext-а. Но это решается на уровне абстракции. У нас на одном проекте есть инъекция DbContext через авто-фабрику IIndex (Autofac), решение связано как раз из-за наличия более одного DbContext-а. ... |
|||
:
Нравится:
Не нравится:
|
|||
05.11.2020, 00:21 |
|
Иньекция DbContext
|
|||
---|---|---|---|
#18+
fkthat В принципе, есть-то опция, чтобы регистрировать DbContext как transient DbContext как бы по природе не совсем транзиентный :) ... |
|||
:
Нравится:
Не нравится:
|
|||
05.11.2020, 00:22 |
|
Иньекция DbContext
|
|||
---|---|---|---|
#18+
hVostt Если у тебя будет transient, ты огребёшь проблем и потерю в производительности. Врят ли. Кстати, по производительности. Если ты сделаешь подряд запросы, типа Код: c# 1. 2.
То объект тебе вернет один и тот же, но у тебя все равно будет два запроса к БД, т.е. кеша все равно нет. hVostt У нас на одном проекте есть инъекция DbContext через авто-фабрику IIndex (Autofac) Всегда нравилась эта его фича. Особенно с инжектом Func<IService> - там даже фабрики в большинстве случаев не надо. ... |
|||
:
Нравится:
Не нравится:
|
|||
05.11.2020, 00:51 |
|
Иньекция DbContext
|
|||
---|---|---|---|
#18+
hVostt DbContext как бы по природе не совсем транзиентный :) Практически все сценарии работы с ним в ASP.NET - "запросил -> изменил -> сохранил", а потом он уже становится не нужен. Если какая-то десктопная аппликуха, то там вполне может быть и по другому, но в вебе само по себе все считай транзитивное из-за его stateless натуры. ... |
|||
:
Нравится:
Не нравится:
|
|||
05.11.2020, 00:57 |
|
Иньекция DbContext
|
|||
---|---|---|---|
#18+
fkthat Врят ли. Кстати, по производительности. Если ты сделаешь подряд запросы, типа Код: c# 1. 2.
Тут программист сам должен понимать, что конкретно такой запрос выполнится дважды. Если у тебя прокси-ентити, то обращения по навигационной сущности не будут запрошены дважды. Если ты обращаешься к справочникам нормальным образом через Find(...), то каждая единица будет запрошена только один раз, а загруженные ранее в любом качестве не будут запрошены из БД, а взяты из кеша. Если у тебя сложная логика работы с сущностями, то кеш довольно большую роль играет. Но самое главное, если ты будешь работать с транзиентом, тебе придётся атачить ранее полученные сущности из других экземпляров контекста, иначе нарвёшься на грабли. Так и не понял, а какие проблемы со скоупом? :) ... |
|||
:
Нравится:
Не нравится:
|
|||
05.11.2020, 01:33 |
|
Иньекция DbContext
|
|||
---|---|---|---|
#18+
fkthat Практически все сценарии работы с ним в ASP.NET - "запросил -> изменил -> сохранил", а потом он уже становится не нужен. Если какая-то десктопная аппликуха, то там вполне может быть и по другому, но в вебе само по себе все считай транзитивное из-за его stateless натуры. Не вопрос, всё верно. Но в рамках запроса у тебя может быть несколько действий с БД. ДбКонтекст это же не только транслятор LINQ=>SQL. Если тебе именно транлятор нужен, то EF выбор так себе. ... |
|||
:
Нравится:
Не нравится:
|
|||
05.11.2020, 01:35 |
|
Иньекция DbContext
|
|||
---|---|---|---|
#18+
fkthat, Вообще, за SingleOrDefault по айдишнику нужно бить по пальцам :) Всегда нужно использовать Find(), прям железно. ... |
|||
:
Нравится:
Не нравится:
|
|||
05.11.2020, 01:36 |
|
Иньекция DbContext
|
|||
---|---|---|---|
#18+
тот не ловкий момент с трансет я думал чутка не так но работает все) капец как стыдно ... |
|||
:
Нравится:
Не нравится:
|
|||
05.11.2020, 08:28 |
|
Иньекция DbContext
|
|||
---|---|---|---|
#18+
hVostt fkthat, Вообще, за SingleOrDefault по айдишнику нужно бить по пальцам :) Всегда нужно использовать Find(), прям железно. Почему? ... |
|||
:
Нравится:
Не нравится:
|
|||
05.11.2020, 09:01 |
|
Иньекция DbContext
|
|||
---|---|---|---|
#18+
Фабрика по определению решает совершенно другие проблемы-неопределенность получения конкретного типа DbContext в рантайме. Вышеуказанной проблемы у ТС нет. Инъекция фабрики, которая выдаст DbContext вместо самого DbContext это просто добавление еще ненужного слоя абстракции. Хотя возможно ТС хочет, чтобы фабрика выдавала или Scoped или Transient экземпляр? Просьба более подробно раскрыть этот момент. ... |
|||
:
Нравится:
Не нравится:
|
|||
05.11.2020, 09:06 |
|
Иньекция DbContext
|
|||
---|---|---|---|
#18+
hVostt Не вопрос, всё верно. Но в рамках запроса у тебя может быть несколько действий с БД. ДбКонтекст это же не только транслятор LINQ=>SQL. Если тебе именно транлятор нужен, то EF выбор так себе. 1) Сервис А использует контекст и вызывает сервис Б, сервис Б тоже использует контекст, но не знает (и не должен ничего знать) про сервис А, т.к. инкапсуляция, single responsibility и все такое. И, понятно, что он тем более не знает что там перед ним сервис А с контекстом натворил. Запросто можно нарваться на какие-нибудь неожиданности. 2) Сервис А использует контекст и вызывает сервис Б. Сервис Б использует контекст и сохраняет свои изменения. Если сервис А перед вызовом Б внес свои изменения и еще не сохранял, то сервис Б сам того не ведая сохранит и их тоже и это как-то некрасиво. В общем, глобальный объект это глобальный объект, от того что его назвали красивым словом "scoped" он глобальным быть не перестал, разве что его "глобальность" несколько ограничили. ... |
|||
:
Нравится:
Не нравится:
|
|||
05.11.2020, 09:17 |
|
Иньекция DbContext
|
|||
---|---|---|---|
#18+
vb_sub Хотя возможно ТС хочет, чтобы фабрика выдавала или Scoped или Transient экземпляр? Просьба более подробно раскрыть этот момент. Я хочу (или, лучше сказать, мне это кажется более правильным), чтобы каждый отдельный сервис, вызываемый в пределах скоупа, получал свой собственный экземпляр контекста, а не фигачил все свои изменения/сохранения в общий, рискуя нарваться на какие-либо конфликты с другими сервисами, вызываемыми в этом же скоупе. ... |
|||
:
Нравится:
Не нравится:
|
|||
05.11.2020, 09:21 |
|
Иньекция DbContext
|
|||
---|---|---|---|
#18+
hVostt Но в рамках запроса у тебя может быть несколько действий с БД. Я бы лучше сказал "в рамках вызова сервиса". Потому что если несколько взаимосвязанных запросов раскиданы по нескольким сервисам, то это вообще какой-то говнодизайн, нарушается весь loose coupling. А если в рамках одного вызова сервиса, то какие проблемы - получи контекст, сделай там хоть стопятьсот запросов и изменений, потом все одним разом сохрани - обычный Unit of work. И вот, кстати цикл работы с UoW (загрузи -> измени -> сохрани) это по сути отдельная логическая транзакция (не зря ведь его назвали "unit"). И существует очень общее правило: "при завершении (коммит/роллбек) транзакция забывает свое состояние". Т.е. любая транзакция никогда не должна использовать данные полученные в другой транзакции. А шейринг контекста между сервисами это правило нарушает. ... |
|||
:
Нравится:
Не нравится:
|
|||
05.11.2020, 09:35 |
|
Иньекция DbContext
|
|||
---|---|---|---|
#18+
handmadeFromRu тот не ловкий момент с трансет я думал чутка не так но работает все) капец как стыдно Тут, на самом деле, есть еще подводный камень, про который надо помнить - даже транзитивный объект живет все время жизни скоупа в котором он создан. В ASP.NET это проблем не создает, т.к. сами скоупы все короткоживущие, но, скажем, в каком-нибудь десктопном приложении это следует учитывать. ... |
|||
:
Нравится:
Не нравится:
|
|||
05.11.2020, 09:43 |
|
Иньекция DbContext
|
|||
---|---|---|---|
#18+
fkthat handmadeFromRu тот не ловкий момент с трансет я думал чутка не так но работает все) капец как стыдно Тут, на самом деле, есть еще подводный камень, про который надо помнить - даже транзитивный объект живет все время жизни скоупа в котором он создан. В ASP.NET это проблем не создает, т.к. сами скоупы все короткоживущие, но, скажем, в каком-нибудь десктопном приложении это следует учитывать. да я эт понимаю. схема то что я описал все равно работала так как учитывал что скоуп очищает диспосет ... |
|||
:
Нравится:
Не нравится:
|
|||
05.11.2020, 09:53 |
|
Иньекция DbContext
|
|||
---|---|---|---|
#18+
fkthat hVostt fkthat, Вообще, за SingleOrDefault по айдишнику нужно бить по пальцам :) Всегда нужно использовать Find(), прям железно. Почему? Find() берёт из кеша :) fkthat 1) Сервис А использует контекст и вызывает сервис Б, сервис Б тоже использует контекст, но не знает (и не должен ничего знать) про сервис А, т.к. инкапсуляция, single responsibility и все такое. И, понятно, что он тем более не знает что там перед ним сервис А с контекстом натворил. Запросто можно нарваться на какие-нибудь неожиданности. Ты говоришь о том, что контекст кто-то может сломать? Ну так это вообще изначально плохой кейс. Нельзя ломать контекст и даже предполагать его поломку. fkthat 2) Сервис А использует контекст и вызывает сервис Б. Сервис Б использует контекст и сохраняет свои изменения. Если сервис А перед вызовом Б внес свои изменения и еще не сохранял, то сервис Б сам того не ведая сохранит и их тоже и это как-то некрасиво. Да, всё верно, если другой сервис вызвал SaveChanges контекста, это сохранит все изменения контекста. И это, разумеется, правильно. Ибо ты сохраняешь состояние. То, как ты описал, выглядит как независимые изменения, в таком случае ты тупо идёшь против самой концепции контекста. Как бы идёшь в разрез роли компонента в проекте. Ибо это UOW, а он не может быть точечным и независимым в рамках всей операции (читай, запроса). И с другой стороны, если SaveChanges у тебя вызывается на разных уровнях, это очень кривая архитектура. Сохранение должно быть строго в одном слое. ... |
|||
:
Нравится:
Не нравится:
|
|||
05.11.2020, 17:09 |
|
Иньекция DbContext
|
|||
---|---|---|---|
#18+
hVostt, Да лично я-то никогда на практике со scoped data context проблем не имел, но просто вижу возможность их поимения. Потому что, повторюсь, scoped это по сути нечто глобальное, к чему имееет доступ все что только можно. А что-то глобальное это всегда возможность выстрелить себе в ногу. Это-то мне и не нравится. Вот, смотри, такой, допустим, воображаемый сценарий. 1) Сервис А добавляет в контекст запись о покупке 2) Сервис А вызывает сервис Б чтобы вычислить НДС 3) Сервис А добавляет НДС в запись о покупке 4) Сервис А сохраняет изменения через SaveChange Выглядит все нормально. Но вот. Я как разработчик сервиса А не знаю, да и знать не хочу как внутри устроен сервис Б. И поэтому я в душе не ведаю, что сервис Б для чего-то и сам вызывает SaveChanges (кто его там знает, может он какой-то аудит вызовов в базу пишет) - и он в этом вполне прав, потому что его тоже не должно волновать, что и как я перед его вызовом делал. И при таком сценарии между п.2 и п.3 в БД окажется некорректная запись (с ценой, но без НДС), которую, между прочим, какой-то другой запрос может прочитать, т.к. другой запрос будет в другом скоупе и у него будет "чистый" датаконтекст. С т.з. правильного использования UoW я пока вижу только такой вариант, чтобы над всеми этими сервисами ставить какой-то сервис-оркестратор, который будет заниматься только тем, что вызывать нужные сервисы, а потом одним махом делать общий "коммит" в виде вызова SaveChanges. ... |
|||
:
Нравится:
Не нравится:
|
|||
05.11.2020, 19:28 |
|
Иньекция DbContext
|
|||
---|---|---|---|
#18+
hVostt И это, разумеется, правильно. Ибо ты сохраняешь состояние. Чего же тут правильного, если я вызывая какой-то сервис, который писал вообще не я, должен всегда думать: "а не сохранит ли он мне то моё, что я еще пока что сохранять еще не хочу". Это вообще нарушение всех принципов модульности и инкапсуляции. ... |
|||
:
Нравится:
Не нравится:
|
|||
05.11.2020, 19:31 |
|
Иньекция DbContext
|
|||
---|---|---|---|
#18+
fkthat Вот, смотри, такой, допустим, воображаемый сценарий. 1) Сервис А добавляет в контекст запись о покупке 2) Сервис А вызывает сервис Б чтобы вычислить НДС 3) Сервис А добавляет НДС в запись о покупке 4) Сервис А сохраняет изменения через SaveChange Проблема в п.4 Сервис А не должен сохранять изменения :) fkthat Выглядит все нормально. Но вот. Я как разработчик сервиса А не знаю, да и знать не хочу как внутри устроен сервис Б. И поэтому я в душе не ведаю, что сервис Б для чего-то и сам вызывает SaveChanges И поэтому ни Б, ни В, ни кто-то ещё не должен отвечать за сохранение. Это логика подготовки изменений. Конечное решение принимается на самом верхнем уровне. Ибо. Если ты последовательно выполняешь сервисы А, Б, В... и т.д., и хочешь сохранить тогда и только тогда, когда все сервисы корректно отработали, ты хрен это сделаешь, если каждый сервис будет самовольно что-то там сохранять (совсем страх потеряли..) Подумай над этим :) Смысл UOW в том, что ты только в одном месте принимаешь конечно решение. И для тестирования хорошо. А ещё инетресней всё становится, когда ты переписал всё в функциональном стиле, где вообще за эффекты в виде сохранения чего-то там куда-то внутри сервисных функций, бьют ногами :) ... |
|||
:
Нравится:
Не нравится:
|
|||
06.11.2020, 08:59 |
|
Иньекция DbContext
|
|||
---|---|---|---|
#18+
fkthat над всеми этими сервисами ставить какой-то сервис-оркестратор, который будет заниматься только тем, что вызывать нужные сервисы Ну вообще, задача разработки не усложнять, а упрощать. Сервис-оркестратор у тебя уже из коробки есть. Это контроллер. ... |
|||
:
Нравится:
Не нравится:
|
|||
06.11.2020, 09:00 |
|
Иньекция DbContext
|
|||
---|---|---|---|
#18+
fkthat hVostt И это, разумеется, правильно. Ибо ты сохраняешь состояние. Чего же тут правильного, если я вызывая какой-то сервис, который писал вообще не я, должен всегда думать: "а не сохранит ли он мне то моё, что я еще пока что сохранять еще не хочу". Это вообще нарушение всех принципов модульности и инкапсуляции. Ну и чем поможет transient здесь? Ну потеряешь ты вообще всякий контроль, чем лучше? Какой-то левый сервис что-то там сохранит, а тебе это не надо, если на втором шаге условие не выполняется. Что делать? Ничего, грызть локоть. И зачем такое нужно? :) ... |
|||
:
Нравится:
Не нравится:
|
|||
06.11.2020, 09:02 |
|
Иньекция DbContext
|
|||
---|---|---|---|
#18+
hVostt Ну и чем поможет transient здесь? Ну потеряешь ты вообще всякий контроль, чем лучше? Ничего я не потяряю. Мой сервис будет работать со своим экземпляром контекстьа. Другой сервис будет работать со своим. Это как локальные переменные vs глобальные - меняя локальную переменную я гарантированно ни на что что за пределами её видимости не повлияю, поэтом я не парюсь ни о том можно ли мне и как её менять и так же не парюсь о том, что кто-то без моего ведома её поменяет. hVostt Какой-то левый сервис что-то там сохранит, Почему левый? Обычный сервис из проекта, который мне для моих целей из моего сервиса нужен. Или же уже сервисам нельзя вызывать другие сервисы? Это еще очень напоминает известную замороку со вложенными транзакциями в SQL. Там из-за этого, если ты хочешь внутри SP делать транзакцию приходится ставить проверки не находишься ли ты уже внутри транзакции. По крайней мере, когда-то это было так. ... |
|||
:
Нравится:
Не нравится:
|
|||
06.11.2020, 11:48 |
|
Иньекция DbContext
|
|||
---|---|---|---|
#18+
fkthat Ничего я не потяряю. Мой сервис будет работать со своим экземпляром контекстьа. Другой сервис будет работать со своим. Это как локальные переменные vs глобальные - меняя локальную переменную я гарантированно ни на что что за пределами её видимости не повлияю, поэтом я не парюсь ни о том можно ли мне и как её менять и так же не парюсь о том, что кто-то без моего ведома её поменяет. Не совсем понял, нафига тебе это. Давай абстрактно, вот есть POST-запрос. В рамках запроса у тебя может выполняться ряд операций разных сервисов. С точки зрения интерфейса, это _единая операция_, клиенту как бы плевать сколько у тебя там сервисов и вообще на все твои 100500 слоёв и сервисов положить. Вся операция -- единое целое, они либо она полностью выполнится, либо отвалится с ошибкой. Какие ты там собрался промежуточные сохранения использовать, для чего? Зачем эти половинчатые изменения? :) Как бы DbContext в скоупе идеально ложится на эту концепцию. На этом принципе выполнено огромное дохренища проектов, и первый раз слышу, чтобы кого-то это не устраивало :)) ... |
|||
:
Нравится:
Не нравится:
|
|||
06.11.2020, 13:38 |
|
Иньекция DbContext
|
|||
---|---|---|---|
#18+
fkthat Это еще очень напоминает известную замороку со вложенными транзакциями в SQL. Там из-за этого, если ты хочешь внутри SP делать транзакцию приходится ставить проверки не находишься ли ты уже внутри транзакции. По крайней мере, когда-то это было так. Ну так вот scoped контекст эту проблему решает. ... |
|||
:
Нравится:
Не нравится:
|
|||
06.11.2020, 13:40 |
|
Иньекция DbContext
|
|||
---|---|---|---|
#18+
hVostt Как бы DbContext в скоупе идеально ложится на эту концепцию. На этом принципе выполнено огромное дохренища проектов, и первый раз слышу, чтобы кого-то это не устраивало :)) Ну и где там SaveChanges происходит? В конце вызова контроллера? Смахивает на костыль какой-то. ... |
|||
:
Нравится:
Не нравится:
|
|||
06.11.2020, 16:57 |
|
Иньекция DbContext
|
|||
---|---|---|---|
#18+
hVostt fkthat Это еще очень напоминает известную замороку со вложенными транзакциями в SQL. Там из-за этого, если ты хочешь внутри SP делать транзакцию приходится ставить проверки не находишься ли ты уже внутри транзакции. По крайней мере, когда-то это было так. Ну так вот scoped контекст эту проблему решает. Как решает? ... |
|||
:
Нравится:
Не нравится:
|
|||
06.11.2020, 16:58 |
|
Иньекция DbContext
|
|||
---|---|---|---|
#18+
fkthat hVostt Как бы DbContext в скоупе идеально ложится на эту концепцию. На этом принципе выполнено огромное дохренища проектов, и первый раз слышу, чтобы кого-то это не устраивало :)) Ну и где там SaveChanges происходит? В конце вызова контроллера? Смахивает на костыль какой-то. ну давай на примере: Код: c# 1. 2. 3. 4. 5. 6. 7. 8. 9. 10.
в _service1 ты что-то сохранил, а на _service2 у тебя что-то бахнет, значит мы вылетим из действия с искаверканными данными в БД (по бизнесу). норм? это не костыль, это большая увесистая грабля с гранатой на ручке. ... |
|||
:
Нравится:
Не нравится:
|
|||
08.11.2020, 01:44 |
|
Иньекция DbContext
|
|||
---|---|---|---|
#18+
fkthat hVostt пропущено... Ну так вот scoped контекст эту проблему решает. Как решает? DbContext это UOW. Запрос это атомарное действие, которое должно полностью выполнится, а не наполовинку. UOW для этого и создан. Он не создан, чтобы тупо сейвить каждой изменение каждой фигни в проекте. Это общее сохранение всей проделанной работы. ... |
|||
:
Нравится:
Не нравится:
|
|||
08.11.2020, 01:46 |
|
Иньекция DbContext
|
|||
---|---|---|---|
#18+
fkthat, Не, я могу конечно ошибаться в твоём случае. Просто не понимаю пока сути проблемы.. Для меня transient DbContext это дичь :) ... |
|||
:
Нравится:
Не нравится:
|
|||
08.11.2020, 01:49 |
|
Иньекция DbContext
|
|||
---|---|---|---|
#18+
hVostt Он не создан, чтобы тупо сейвить каждой изменение каждой фигни в проекте. Это общее сохранение всей проделанной работы. Вот. Теперь смотри. Я пишу компонент (сервис). Меня заботит только то, что этот сервис должен делать то, для чего он предназначен. Меня вообще не волнует и не должно волновать, кто, как, и в каком сценарии его использует. А теперь, откуда мне знать, что тот, кто его использует, или тот, кто использует того, кто его использует действительно сохраняет изменения. ... |
|||
:
Нравится:
Не нравится:
|
|||
08.11.2020, 03:29 |
|
Иньекция DbContext
|
|||
---|---|---|---|
#18+
hVostt в _service1 ты что-то сохранил, а на _service2 у тебя что-то бахнет, значит мы вылетим из действия с искаверканными данными в БД (по бизнесу). Если все три вызова должны быть одной транзакцией, значит их надо явно объединять в одну транзакцию. При твоем подходе, получается, что SaveChanges надо вообще куда-то в middleware выносить. А, кстати, в твоем примере кода, если ничего-таки не бахнет, то кто SaveChanges будет делать? ... |
|||
:
Нравится:
Не нравится:
|
|||
08.11.2020, 03:33 |
|
Иньекция DbContext
|
|||
---|---|---|---|
#18+
fkthat Вот. Теперь смотри. Я пишу компонент (сервис). Меня заботит только то, что этот сервис должен делать то, для чего он предназначен. Меня вообще не волнует и не должно волновать, кто, как, и в каком сценарии его использует. А теперь, откуда мне знать, что тот, кто его использует, или тот, кто использует того, кто его использует действительно сохраняет изменения. Это нарушение SRP. DbContext это абстракция, а не работа с БД. Одна из задач этой абстракции, это UOW. Другими словами, ты говоришь, что твой сервис хочет работать с БД изолировано. Значит у него либо должен быть свой собственный личный DbContext, о котором никто ничего не знает, никто с ним больше не работает и вообще понятия не имеет, либо работать с БД напрямую. fkthat Если все три вызова должны быть одной транзакцией, значит их надо явно объединять в одну транзакцию. При твоем подходе, получается, что SaveChanges надо вообще куда-то в middleware выносить. А, кстати, в твоем примере кода, если ничего-таки не бахнет, то кто SaveChanges будет делать? Если в контексте ASP.NET, то контроллер. ... |
|||
:
Нравится:
Не нравится:
|
|||
09.11.2020, 01:17 |
|
Иньекция DbContext
|
|||
---|---|---|---|
#18+
fkthat, И всё же. Может есть реальный кейс, с которым ты столкнулся? Я просто за все свои множество лет опыта никогда таких проблем не ловил, наверное потому что воспринимают DbContext именно так, как он был задуман :) ... |
|||
:
Нравится:
Не нравится:
|
|||
09.11.2020, 01:19 |
|
Иньекция DbContext
|
|||
---|---|---|---|
#18+
hVostt Если в контексте ASP.NET, то контроллер. Т.е. инжектить DbContext в контроллер? ... |
|||
:
Нравится:
Не нравится:
|
|||
09.11.2020, 06:17 |
|
Иньекция DbContext
|
|||
---|---|---|---|
#18+
hVostt Другими словами, ты говоришь, что твой сервис хочет работать с БД изолировано. Да, потому что иначе он просто не реюзабельный, потому что становится зависимым от того, что снаружи него и как оно само работает. ... |
|||
:
Нравится:
Не нравится:
|
|||
09.11.2020, 06:20 |
|
Иньекция DbContext
|
|||
---|---|---|---|
#18+
hVostt И всё же. Может есть реальный кейс, с которым ты столкнулся? Я просто за все свои множество лет опыта никогда таких проблем не ловил:) Я тоже, но я же с самого начала и написал, "не ловил, но вижу возможность поймать". Впрочем, один раз что-то было, связанное с использованием Attach, впрочем, я не сторонник его использования, т.ч. это, скорее, исключение. ... |
|||
:
Нравится:
Не нравится:
|
|||
09.11.2020, 06:23 |
|
Иньекция DbContext
|
|||
---|---|---|---|
#18+
fkthat hVostt Если в контексте ASP.NET, то контроллер. Т.е. инжектить DbContext в контроллер? Не совсем. Инжектить IUnitOfWork, который реализуется DbContext-ом. fkthat Да, потому что иначе он просто не реюзабельный, потому что становится зависимым от того, что снаружи него и как оно само работает. Он и должен быть зависимым, DbContext это полная абстракция над хранилищем. fkthat Я тоже, но я же с самого начала и написал, "не ловил, но вижу возможность поймать". Впрочем, один раз что-то было, связанное с использованием Attach, впрочем, я не сторонник его использования, т.ч. это, скорее, исключение. Ну если не ловил, зачем заморачиваться :) Я вот не ловил, и даже не вижу проблем. То о чём ты говоришь, выглядит примерно как: — а что если вилкой в глаз тыкнуть, то что? давайте пробку на вилку оденем! ... |
|||
:
Нравится:
Не нравится:
|
|||
09.11.2020, 11:25 |
|
Иньекция DbContext
|
|||
---|---|---|---|
#18+
hVostt Не совсем. Инжектить IUnitOfWork, который реализуется DbContext-ом. Тоже плохо. Потому что IUnitOfWork это все равно DAL, а не BL. fkthat Он и должен быть зависимым. Сервис, работа которого зависит от других сервисов, про которые он даже ничего не знает? Отвлечемся вообще от БД и контекста. Допустим, у меня стек вызов сервисов А->B>C->D и оказывается, что поведение сервиса D зависитот того, что делал сервис A перед тем как вызвал B. Это уже не модульное приложение будет, а какая-то адова лапша. ... |
|||
:
Нравится:
Не нравится:
|
|||
09.11.2020, 12:45 |
|
Иньекция DbContext
|
|||
---|---|---|---|
#18+
Ну вот смотри (как я расшифровываю подход Хвоста), само название Db Context делает его похожим на артефакты типа HttpContext и иже с ним. То есть вот у тебя запрос, он же скоуп, на него формируется HttpContext, DbContext еще какие-то контексты. Каждый из сервисов может модифицировать что-то в этом контексте, но закрытие и финальное решение по этим контекстам происходит именно в момент окончания работы со скоупом, ну в данном случае - это последние команды контроллера. ... |
|||
:
Нравится:
Не нравится:
|
|||
09.11.2020, 12:51 |
|
Иньекция DbContext
|
|||
---|---|---|---|
#18+
Shocker.Pro ну в данном случае - это последние команды контроллера. А если он где-то в фильтре используется, или в middleware? Да и, как я уже писал, вызывать DAL прямо из контроллера это уже сама по себе хрень какая-то. А по-хорошему, если что-то шарится между разными компонентами, должно быть иммутабельно. Поскольку дбконтекст таковым не является, то от этого можно вполне ожидать какой-нибудь беды. ... |
|||
:
Нравится:
Не нравится:
|
|||
09.11.2020, 13:18 |
|
Иньекция DbContext
|
|||
---|---|---|---|
#18+
fkthat Да и, как я уже писал, вызывать DAL прямо из контроллера это уже сама по себе хрень какая-то. Это не DAL, это UOW. UOW может реализовывать не только SaveChanges в DbContext-а, но выполнять любые другие завершающие операции: отправка сообщений в очередь, инициация событий, сохранение данных в другие репозитории. Мыслить рамками, что DbContext это абсолютно вся работа с данными что есть -- вредно. Это не так. fkthat А по-хорошему, если что-то шарится между разными компонентами, должно быть иммутабельно. Поскольку дбконтекст таковым не является, то от этого можно вполне ожидать какой-нибудь беды. Именно является. Как я уже сказал, это UOW. Проблема в твоих рассуждениях, что ты за DbContext видишь какой-то маленький кусочек, но не видишь остального. Ну и проблемы прям люто надуманные. Я не представляю что можно сделать, чтобы контекст в скоупе было плохим решением. Это надо ещё постараться. Ну и это признак явного говнокодища :) ... |
|||
:
Нравится:
Не нравится:
|
|||
09.11.2020, 14:31 |
|
Иньекция DbContext
|
|||
---|---|---|---|
#18+
Shocker.Pro Ну вот смотри (как я расшифровываю подход Хвоста), само название Db Context делает его похожим на артефакты типа HttpContext и иже с ним. То есть вот у тебя запрос, он же скоуп, на него формируется HttpContext, DbContext еще какие-то контексты. Каждый из сервисов может модифицировать что-то в этом контексте, но закрытие и финальное решение по этим контекстам происходит именно в момент окончания работы со скоупом, ну в данном случае - это последние команды контроллера. Всё верно. Просто со времён развития идеи fat controller is evil, люди ушли в другую крайность, которая ещё хуже, чем жирные контроллеры. Именно контроллер отвечает за правильную организацию обработки запроса. От слова контроллер же! ... |
|||
:
Нравится:
Не нравится:
|
|||
09.11.2020, 14:32 |
|
Иньекция DbContext
|
|||
---|---|---|---|
#18+
fkthat А если он где-то в фильтре используется, или в middleware? И что? Не вижу никаких проблем. В фильтре или в миддлеваре вообще нужно избегать работы с DbContext. И действовать через разумные абстракции. ... |
|||
:
Нравится:
Не нравится:
|
|||
09.11.2020, 14:33 |
|
Иньекция DbContext
|
|||
---|---|---|---|
#18+
hVostt В фильтре или в миддлеваре вообще нужно избегать работы с DbContext. И действовать через разумные абстракции. А я и не сказал, что напрямую использовать. Он может использоваться через какой-либо сервис BL. hVostt Именно контроллер отвечает за правильную организацию обработки запроса. От слова контроллер же! Контроллер отвечает за трансляцию HTTP-запроса в вызов сервиса(ов) BL и трансляцию ответа от BL в HTTP-ответ. Знать что-то о том, что лежит ниже BL он не имеет права. ... |
|||
:
Нравится:
Не нравится:
|
|||
09.11.2020, 14:50 |
|
Иньекция DbContext
|
|||
---|---|---|---|
#18+
fkthat hVostt В фильтре или в миддлеваре вообще нужно избегать работы с DbContext. И действовать через разумные абстракции. А я и не сказал, что напрямую использовать. Он может использоваться через какой-либо сервис BL. Ну фиг знает, может у тебя фильтр для записи в БД лога запросов. И отсюда растут ноги у проблемы :) Конечно, так делать нельзя, DbContext для таких задач не предназначен. fkthat Контроллер отвечает за трансляцию HTTP-запроса в вызов сервиса(ов) BL и трансляцию ответа от BL в HTTP-ответ. Знать что-то о том, что лежит ниже BL он не имеет права. А он и не знает. Не вижу никаких противоречий ... |
|||
:
Нравится:
Не нравится:
|
|||
09.11.2020, 15:30 |
|
Иньекция DbContext
|
|||
---|---|---|---|
#18+
hVostt Ну фиг знает, может у тебя фильтр для записи в БД лога запросов. И отсюда растут ноги у проблемы :) ьзя, DbContext для таких задач не предназначен. У меня такого фильтра нет, я из ума не выжил, но я тут говорю о модульности. Я вызываю сервис, который писал вообще не я. Я не знаю и знать не хочу про него ничего, кроме того, что у него должно быть на входе (параметры) и на выходе (возвращаемое значение). А тут оказывается, что этот сервис втайне от меня изменяет окружение (DbContext) вообще всего что только можно, что в моем скоупе. Бог даже с ним с DbContext. Замени его на любой синглтон (или на скоупед, что тот же синглтон и есть, только для контекста), состояние которого кто угодно может поменять, и будет то же самое. Именно это мне и не нравится. ... |
|||
:
Нравится:
Не нравится:
|
|||
09.11.2020, 15:39 |
|
Иньекция DbContext
|
|||
---|---|---|---|
#18+
fkthat А тут оказывается, что этот сервис втайне от меня изменяет окружение (DbContext) вообще всего что только можно ПОГОДИ! А если _этот сервис_ в тайне от тебя в БД что-то пишет? Что тогда? При чём тут тогда DbContext? :) И что он там такого может _изменить_, что повлияет на тебя? Я просто не понимаю. Это что вообще он там может такого сделать? fkthat Замени его на любой синглтон (или на скоупед, что тот же синглтон и есть, только для контекста), состояние которого кто угодно может поменять, и будет то же самое. Именно это мне и не нравится. Всё же хотелось бы более приземлённых примеров, в области практики. Мне на самом деле в архитектуре .NET, библиотек и решений много чего не нравится. Я даже не представляю что должно случиться, чтобы мне всё-всё нравилось :) Если такое вдруг случится, значит я достиг абсолютного дзена, и могу отделиться от своей земной оболочки и переместиться в абсолютно идеальный духовный мир. Надо как-то немного конкретней выделить проблему. ... |
|||
:
Нравится:
Не нравится:
|
|||
09.11.2020, 17:24 |
|
Иньекция DbContext
|
|||
---|---|---|---|
#18+
hVostt А если _этот сервис_ в тайне от тебя в БД что-то пишет? Так пусть себе и пишет. Суть в том, что все при этом должно быть сделано так, чтобы меня, как потребителя этого сервиса это не волновало. Ты пользуешься кучей .NET API - а вдруг оно тоже что-то там куда-то пишет, что ты не знаешь - тебя это просто не волнует и все, т.к. оно если и пишет, то делает это так, что тебя не трогает. ... |
|||
:
Нравится:
Не нравится:
|
|||
09.11.2020, 18:50 |
|
Иньекция DbContext
|
|||
---|---|---|---|
#18+
fkthat Так пусть себе и пишет. Суть в том, что все при этом должно быть сделано так, чтобы меня, как потребителя этого сервиса это не волновало. Ты пользуешься кучей .NET API - а вдруг оно тоже что-то там куда-то пишет, что ты не знаешь - тебя это просто не волнует и все, т.к. оно если и пишет, то делает это так, что тебя не трогает. Ну давай тогды IMemoryCache тоже сделаем транзиентным Как я уже говорил, от общего DbContext в скоупе есть реальный профит. Именно так он рекомендуется к использованию. Теоретически это тоже объясняется одним предложением: DbContext это UOW. Какие-то надуманные и высосанные из пальца проблемы, якобы кто-то другой в мой контекст влезет и что-то там сломает на практике совершенно не подтверждаются. Проект, который построен на EF уже по факту обладает довольно высокой связностью. Давай я пример ещё приведу. У тебя есть приложение на EF с контекстом. Ты решил добавить себе фоновые службы, вынес в отдельное сервисное приложение, как полагается. Взял хенгфаер. Теперь зырь: https://github.com/sergezhigunov/Hangfire.EntityFrameworkCore Намекаю на то, что задачи Hangfire никак не пересекаются с задачами твоего DbContext. Значит это другой контекст. И ещё намекаю, раз у тебя в рамках одного DbContext реализуются совершенно не связанные задачи и разнесённая на пару парсеков логика, значит у тебя явно нарушение SRP и ты пытаешься вылечить зрение через ж-пу :) ... |
|||
:
Нравится:
Не нравится:
|
|||
09.11.2020, 20:05 |
|
Иньекция DbContext
|
|||
---|---|---|---|
#18+
hVostt И ещё намекаю, раз у тебя в рамках одного DbContext реализуются совершенно не связанные задачи и разнесённая на пару парсеков логика, значит у тебя явно нарушение SRP и ты пытаешься вылечить зрение через ж-пу :) Ага. Под каждый сервис БЛ будем заводить отдельный контекст и БД. Да что уж там - давай под каждый метод сервиса отдельный контекст. Одна из идей севиса (компонента) это инкапсуляция, что значит, что он не должен никак взаимодействовать со "внешним миром" кроме как через свой интерфейс-контракт. Если он начинает менять какие-то объекты, которые разделяет с другими сервисами, то это уже нарушение инкапсуляции. Неспроста ведь глобальные переменные, а также out, и ref параметры считаются говнокодом (ну, кроме Try-Get шаблона, может быть). Ровно по той же причине. Меня вообще доставляет, когда я регулярно вижу, как всё подряд, не глядя регают в контейнере как singleton или scoped - байты, блин экономят, что ли. ... |
|||
:
Нравится:
Не нравится:
|
|||
09.11.2020, 20:33 |
|
Иньекция DbContext
|
|||
---|---|---|---|
#18+
fkthat, В упор не вижу, как нарушается инкапсуляция DbContext-а. Это ведь итак уже абстракция. Итак контракт. Давай ещё каждый отдельный компонент ЕДИНОГО приложения будет содержать свой драйвер БД, свой пул соединений, свою файловую систему, каждому классу по отдельной плашке памяти и т.д. и т.п. :) Вот сколько мы дискутируем, я так и не увидел ни одного хоть отдалённо приближенному к границам реальности кейса, где была обнаружена проблема, которую ты решаешь :) fkthat Меня вообще доставляет, когда я регулярно вижу, как всё подряд, не глядя регают в контейнере как singleton или scoped - байты, блин экономят, что ли. А почему нет? Вот у меня добрый десяток _изолированных_ компонентов используют DbContext в одном HTTP запросе. Мне что на обработку запроса десяток соединений к одной и той же БД создавать? Инженерия это прежде всего компромисс. Все шаблоны и принципы -- это борьба со сложностью, а не религия. ... |
|||
:
Нравится:
Не нравится:
|
|||
09.11.2020, 21:17 |
|
Иньекция DbContext
|
|||
---|---|---|---|
#18+
ну наверное все ж от задачи и в вебе эт приемлемо. вопрос что если тебе 2 варика надо что придется дописать. меня лично вызывает не понятки что часто делпют репо + Uow поверх орм где по сути также репо и uow. ... |
|||
:
Нравится:
Не нравится:
|
|||
09.11.2020, 21:25 |
|
Иньекция DbContext
|
|||
---|---|---|---|
#18+
handmadeFromRu ну наверное все ж от задачи и в вебе эт приемлемо. вопрос что если тебе 2 варика надо что придется дописать. меня лично вызывает не понятки что часто делпют репо + Uow поверх орм где по сути также репо и uow. продвинутые пацаны юзают CQ(R)S и на эту тему не парятся :) ... |
|||
:
Нравится:
Не нравится:
|
|||
09.11.2020, 21:28 |
|
Иньекция DbContext
|
|||
---|---|---|---|
#18+
hVostt В упор не вижу, как нарушается инкапсуляция DbContext-а. Да никак она не нарушается. Я уже сто раз повторил. Просто один компонент может влиять на поведение другого через data context. Жить с этим можно, но я, все-таки, не вижу в этом ничего хорошего. hVostt Мне что на обработку запроса десяток соединений к одной и той же БД создавать? Еще скажи, что ты не слышал про connection pool и во времена ADO.NET делал один общий объект Connection на все приложение. ... |
|||
:
Нравится:
Не нравится:
|
|||
09.11.2020, 21:31 |
|
Иньекция DbContext
|
|||
---|---|---|---|
#18+
hVostt продвинутые пацаны юзают CQ(R)S и на эту тему не парятся :) А CQRS в базу аки спаситель пешком по воде ходит? ... |
|||
:
Нравится:
Не нравится:
|
|||
09.11.2020, 21:32 |
|
Иньекция DbContext
|
|||
---|---|---|---|
#18+
fkthat Просто один компонент может влиять на поведение другого через data context. Жить с этим можно, но я, все-таки, не вижу в этом ничего хорошего. Так это... я ж привёл пример с кешем. IMemoryCache, любой компонент может повлиять на любой, грохнуть данные по ключам, записать туда мусор. И примеров можно дофига привести. Мы же как-то живём с вилками и ножами, не смотря на всю их смертельную угрозу :) fkthat ще скажи, что ты не слышал про connection pool и во времена ADO.NET делал один общий объект Connection на все приложение. Ну так пул как бы не бесконечный ресурс :) Например, под нагрузками 100-200K rpm и выше, ресурсами не разбрасываются, особенно с необъяснимым выхлопом. ... |
|||
:
Нравится:
Не нравится:
|
|||
09.11.2020, 22:26 |
|
Иньекция DbContext
|
|||
---|---|---|---|
#18+
fkthat hVostt продвинутые пацаны юзают CQ(R)S и на эту тему не парятся :) А CQRS в базу аки спаситель пешком по воде ходит? Так типа ты вообще не тащишь никакой XxxxxContext :) ... |
|||
:
Нравится:
Не нравится:
|
|||
09.11.2020, 22:28 |
|
Иньекция DbContext
|
|||
---|---|---|---|
#18+
hVostt Ну так пул как бы не бесконечный ресурс :) Например, под нагрузками 100-200K rpm и выше, ресурсами не разбрасываются, особенно с необъяснимым выхлопом. Поэтому и best practice это избавляться от соединения как можно быстрее, чтобы оно в пул вернулось, а не тянуть его открытым через весь запрос (впрочем, к ЕФ это отношения не имеет, т.к. у него контекст соединение не держит при себе, а дергает только когда оно надо) ... |
|||
:
Нравится:
Не нравится:
|
|||
09.11.2020, 22:33 |
|
Иньекция DbContext
|
|||
---|---|---|---|
#18+
hVostt Так это... я ж привёл пример с кешем. IMemoryCache, любой компонент может повлиять на любой, грохнуть данные по ключам, записать туда мусор. Это какой-то черезжопный кеш. По нормальному кеш делается тонкой прослойкой декораторов, и его клиент (к примеру, сервис БЛ) прямого доступа туда не имеет. ... |
|||
:
Нравится:
Не нравится:
|
|||
09.11.2020, 22:35 |
|
Иньекция DbContext
|
|||
---|---|---|---|
#18+
fkthat Поэтому и best practice это избавляться от соединения как можно быстрее, чтобы оно в пул вернулось, а не тянуть его открытым через весь запрос (впрочем, к ЕФ это отношения не имеет, т.к. у него контекст соединение не держит при себе, а дергает только когда оно надо) Эти правила как раз применимы к HTTP-запросу. Дальше дробить, это уже ебантяйство какое-то :) fkthat Это какой-то черезжопный кеш. По нормальному кеш делается тонкой прослойкой декораторов, и его клиент (к примеру, сервис БЛ) прямого доступа туда не имеет. Это перпендикулярные вещи совершенно. Добавить кеширующий аспект к запросу это одно, оперировать ключом это другое. ... |
|||
:
Нравится:
Не нравится:
|
|||
09.11.2020, 22:40 |
|
Иньекция DbContext
|
|||
---|---|---|---|
#18+
fkthat, Опять таки "прямого доступа не имеет" -- и вообще закрытый до фанатизма в дупелину БЛ, зачастую являет собой совершенно не сопровождаемое решение, от которого хочется плакать. Не забываем, что кроме уменьшения связанности, нужно думать о хорошей связности. Когда у тебя в проекте 100500 интерфейсов на каждую херню, это уже не смешно. ... |
|||
:
Нравится:
Не нравится:
|
|||
09.11.2020, 22:43 |
|
Иньекция DbContext
|
|||
---|---|---|---|
#18+
hVostt handmadeFromRu ну наверное все ж от задачи и в вебе эт приемлемо. вопрос что если тебе 2 варика надо что придется дописать. меня лично вызывает не понятки что часто делпют репо + Uow поверх орм где по сути также репо и uow. продвинутые пацаны юзают CQ(R)S и на эту тему не парятся :) а как CQRS поможет не шлепать репо и uow? не понимаю ... |
|||
:
Нравится:
Не нравится:
|
|||
09.11.2020, 22:44 |
|
Иньекция DbContext
|
|||
---|---|---|---|
#18+
fkthat hVostt Ну так пул как бы не бесконечный ресурс :) Например, под нагрузками 100-200K rpm и выше, ресурсами не разбрасываются, особенно с необъяснимым выхлопом. Поэтому и best practice это избавляться от соединения как можно быстрее, чтобы оно в пул вернулось, а не тянуть его открытым через весь запрос (впрочем, к ЕФ это отношения не имеет, т.к. у него контекст соединение не держит при себе, а дергает только когда оно надо) чекал он не держит конекшен открытым. открывает закрывает по запросу. ... |
|||
:
Нравится:
Не нравится:
|
|||
09.11.2020, 22:45 |
|
Иньекция DbContext
|
|||
---|---|---|---|
#18+
hVostt fkthat, Опять таки "прямого доступа не имеет" -- и вообще закрытый до фанатизма в дупелину БЛ, зачастую являет собой совершенно не сопровождаемое решение, от которого хочется плакать. Не забываем, что кроме уменьшения связанности, нужно думать о хорошей связности. Когда у тебя в проекте 100500 интерфейсов на каждую херню, это уже не смешно. Не закрытый БЛ, а прозрачное кеширование, когда БЛ кеша просто не видит. Кеширующий декоратор . И как это вообще связано с кол-вом интерфейсов не пойму. Декоратор он на то и декоратор, что имеет тот же интерфейс, что у декорируемого объекта. ... |
|||
:
Нравится:
Не нравится:
|
|||
09.11.2020, 22:52 |
|
Иньекция DbContext
|
|||
---|---|---|---|
#18+
handmadeFromRu а как CQRS поможет не шлепать репо и uow? не понимаю так у тебя для публики команды и запросы никто в репу не ходит, есть она там и или нет. насчёт uow, по-хорошему нужен, но не обязателен, если структура логики позволяет ... |
|||
:
Нравится:
Не нравится:
|
|||
09.11.2020, 22:52 |
|
Иньекция DbContext
|
|||
---|---|---|---|
#18+
handmadeFromRu чекал он не держит конекшен открытым. открывает закрывает по запросу. Да, я об этом выше и написал. ... |
|||
:
Нравится:
Не нравится:
|
|||
09.11.2020, 22:53 |
|
Иньекция DbContext
|
|||
---|---|---|---|
#18+
fkthat Не закрытый БЛ, а прозрачное кеширование, когда БЛ кеша просто не видит. Кеширующий декоратор . Декоратор это паттерн, если реализовывать в лоб, то это довольно уродливое решение. Поэтому лучше говорить про аспекты. fkthat И как это вообще связано с кол-вом интерфейсов не пойму. Декоратор он на то и декоратор, что имеет тот же интерфейс, что у декорируемого объекта. Я так понимаю, ты с кешем работаешь исключительно через декораторы? :) ... |
|||
:
Нравится:
Не нравится:
|
|||
09.11.2020, 22:57 |
|
Иньекция DbContext
|
|||
---|---|---|---|
#18+
hVostt Декоратор это паттерн, если реализовывать в лоб, то это довольно уродливое решение. Поэтому лучше говорить про аспекты. Отличное решение. А аспект это считай синоним. При правильной работе с DI декоратор становится вообще невидимым. Инжектишь интерфейс и получаешь уже задекорированный согласно конфигурации DI объект. У меня для автофака было несколько кастомных расширений, которыми можно было через атрибуты декорировать интерфейсы/объекты разной валидацией, аудитом, обработкой исключений и т.п. hVostt Я так понимаю, ты с кешем работаешь исключительно через декораторы? :) Конечно. Не напрямую же его вызывать, мешая либо логику, либо работу с данными и кеширование. Принцип SR. ... |
|||
:
Нравится:
Не нравится:
|
|||
09.11.2020, 23:26 |
|
Иньекция DbContext
|
|||
---|---|---|---|
#18+
hVostt handmadeFromRu а как CQRS поможет не шлепать репо и uow? не понимаю так у тебя для публики команды и запросы никто в репу не ходит, есть она там и или нет. насчёт uow, по-хорошему нужен, но не обязателен, если структура логики позволяет так я ж про другое имел изначально вот поголовно пишут repo+uow а тот же ef эт уже эта связка. также можно прокидывать в cqrs контектс напрямую но нынче модно абсракцию поверх орм на всякий ... |
|||
:
Нравится:
Не нравится:
|
|||
09.11.2020, 23:33 |
|
Иньекция DbContext
|
|||
---|---|---|---|
#18+
fkthat Отличное решение. А аспект это считай синоним. При правильной работе с DI декоратор становится вообще невидимым. Инжектишь интерфейс и получаешь уже задекорированный согласно конфигурации DI объект. У меня для автофака было несколько кастомных расширений, которыми можно было через атрибуты декорировать интерфейсы/объекты разной валидацией, аудитом, обработкой исключений и т.п. es ) fkthat Конечно. Не напрямую же его вызывать, мешая либо логику, либо работу с данными и кеширование. Принцип SR. Ну тогды ладно :) У нас проектах кеш не только для чистых данных используется, но и много для чего ещё. Хотя, глядя на единственный CRUD проджект, который у нас есть небольшой, там и правда не используется.. ... |
|||
:
Нравится:
Не нравится:
|
|||
09.11.2020, 23:38 |
|
Иньекция DbContext
|
|||
---|---|---|---|
#18+
handmadeFromRu так я ж про другое имел изначально вот поголовно пишут repo+uow а тот же ef эт уже эта связка. также можно прокидывать в cqrs контектс напрямую но нынче модно абсракцию поверх орм на всякий Ну вот как раз на случай обмазать кешем, аудитом и прочей фигнёй) ... |
|||
:
Нравится:
Не нравится:
|
|||
09.11.2020, 23:39 |
|
Иньекция DbContext
|
|||
---|---|---|---|
#18+
hVostt У нас проектах кеш не только для чистых данных используется, но и много для чего ещё. А что в кеше кешировать-то можно кроме данных? Понятно, что можно его просто использовать еще как быстрый key-value store, но это уже как бы и не кеш будет, а просто store для данных. Да и в таком случае не напрямую же использовать опять-таки, а завернуть во что-то хорошо бы. ... |
|||
:
Нравится:
Не нравится:
|
|||
09.11.2020, 23:49 |
|
Иньекция DbContext
|
|||
---|---|---|---|
#18+
fkthat А что в кеше кешировать-то можно кроме данных? Понятно, что можно его просто использовать еще как быстрый key-value store, но это уже как бы и не кеш будет, а просто store для данных. Да и в таком случае не напрямую же использовать опять-таки, а завернуть во что-то хорошо бы. На кеше много чего интересного можно реализовать :) Как бы, и зачастую проще заюзать IMemoryCache, чем городить город из декораторов. Понимаю, что есть динамик кастл и прочие прикольные штуки, но это не молоток, чтобы теперь все-все задачи были гвоздями. Где-то уместно, где-то не очень. ... |
|||
:
Нравится:
Не нравится:
|
|||
09.11.2020, 23:57 |
|
Иньекция DbContext
|
|||
---|---|---|---|
#18+
hVostt На кеше много чего интересного можно реализовать :) Как бы, и зачастую проще заюзать IMemoryCache, чем городить город из декораторов. Понимаю, что есть динамик кастл и прочие прикольные штуки, но это не молоток, чтобы теперь все-все задачи были гвоздями. Где-то уместно, где-то не очень. Так декоратор внутри себя и использует IMemoryCache или подобное - ты что же, думаешь, там в нем какой-то самодельный кеш, что ли. ... |
|||
:
Нравится:
Не нравится:
|
|||
10.11.2020, 07:55 |
|
Иньекция DbContext
|
|||
---|---|---|---|
#18+
fkthat Так декоратор внутри себя и использует IMemoryCache или подобное - ты что же, думаешь, там в нем какой-то самодельный кеш, что ли. Ну вообще, чаще всего уместно использовать IDistributedCache, это всё очень вариативно, чтобы всегда можно было решать декоратором. Поэтому декоратор это как шаблонный паттерн для массивного применения. Точечно пилить декоратор это злостный оверхед. ... |
|||
:
Нравится:
Не нравится:
|
|||
10.11.2020, 12:53 |
|
Иньекция DbContext
|
|||
---|---|---|---|
#18+
hVostt Ну вообще, чаще всего уместно использовать IDistributedCache Да хоть вообще обычный Dictionary - суть-то не в этом. hVostt Точечно пилить декоратор это злостный оверхед. Он пилится за три минуты даже в пьяном угаре. Причем можно сделать базовый декоратор и сделать так, что при желании сменить кеш-провайдер менять надо будет только в одном месте. (впрочем, у нас использовали CacheManager - он уже сам по себе адаптер к любому провайдеру). Декоратор он для того, чтобы 1) отделить код работы с кешем от кода и БЛ и ДАЛ в отдельное место. 2) сделать для БЛ кеш прозрачным - он вообще не будет знать, что он вызывает ДАЛ не напрямую, а через кеш. Может, ты просто под декоратором что-то другое понимаешь? ... |
|||
:
Нравится:
Не нравится:
|
|||
10.11.2020, 13:06 |
|
Иньекция DbContext
|
|||
---|---|---|---|
#18+
fkthat Декоратор он для того, чтобы 1) отделить код работы с кешем от кода и БЛ и ДАЛ в отдельное место. 2) сделать для БЛ кеш прозрачным - он вообще не будет знать, что он вызывает ДАЛ не напрямую, а через кеш. 1) он итак уже отделён в отдельном месте, называется это место IMemoryCache :) 2) вообще он должен знать, так как без нормальной инвалидации такой кеш приносит больше вреда, чем пользы Я всё равно не поддерживаю идеалистические подходы, без зрелого и осознанного понимания что делаешь в каждом конкретном случае. Всё делать через декоратор -- такое себе утверждение. Как бы вот есть отвёртка, есть шуруповёрт, есть пневматика. Для каждого случая, для каждой задачи больше подходит свой инструмент. Говорить, что теперь всё херачим шуруповёртом и гвозди забиваем -- ну хз ))) ... |
|||
:
Нравится:
Не нравится:
|
|||
10.11.2020, 13:15 |
|
Иньекция DbContext
|
|||
---|---|---|---|
#18+
fkthat Может, ты просто под декоратором что-то другое понимаешь? Декоратор это структурный паттерн, это для организации структуры приложения. Нельзя решить все проблемы и задачи работы с кешем структурой. Ибо там дальше может дойти до маразма, и код будет предтсавлять собой десятиэтажную абстракцию, ради решения простой задачи. Это будет медленно работать, жрать ресурсы, а разработчики вынуждены писать тонну оверхеда, ради экономии одной строчки кода. ... |
|||
:
Нравится:
Не нравится:
|
|||
10.11.2020, 13:22 |
|
Иньекция DbContext
|
|||
---|---|---|---|
#18+
hVostt Декоратор это структурный паттерн, это для организации структуры приложения. Деление на типы паттернов часто очень условное. Декоратор он для того, чтобы не изменяя интерфейс объекта менять тем или иным образом его поведение (в том числе и динамически в рантайме). А медиатор, например, относят к паттернам поведения, но его также можно отнести и к структурным (структуру-то приложения он тоже задает). ... |
|||
:
Нравится:
Не нравится:
|
|||
10.11.2020, 13:48 |
|
Иньекция DbContext
|
|||
---|---|---|---|
#18+
hVostt Нельзя решить все проблемы и задачи работы с кешем структурой. Какая структура? Какие жрет ресурсы? Весь кеширующий код, который у меня в декораторе у тебя без декоратора будет в том же виде либо в БЛ, либо в ДАЛ. С тем же успехом можно сказать, что ДАЛ жрет ресурсы, а чтобы не жрал, его весь внутрь БЛ надо поместить. Ты стопудово под декоратором что-то свое понимаешь. ... |
|||
:
Нравится:
Не нравится:
|
|||
10.11.2020, 13:52 |
|
Иньекция DbContext
|
|||
---|---|---|---|
#18+
fkthat Какая структура? Какие жрет ресурсы? Весь кеширующий код, который у меня в декораторе у тебя без декоратора будет в том же виде либо в БЛ, либо в ДАЛ. С тем же успехом можно сказать, что ДАЛ жрет ресурсы, а чтобы не жрал, его весь внутрь БЛ надо поместить. Ты стопудово под декоратором что-то свое понимаешь. Ты лучше расскажи как решаешь проблему с инвалидацией кеша на декораторах :) ... |
|||
:
Нравится:
Не нравится:
|
|||
10.11.2020, 14:41 |
|
Иньекция DbContext
|
|||
---|---|---|---|
#18+
fkthat Деление на типы паттернов часто очень условное. Декоратор он для того, чтобы не изменяя интерфейс объекта менять тем или иным образом его поведение (в том числе и динамически в рантайме). А медиатор, например, относят к паттернам поведения, но его также можно отнести и к структурным (структуру-то приложения он тоже задает). Почему условное-то? Вполне себе конкретное :) Декоратор никоим образом не оказывает влияния на взаимодействие компонентов. А медиатор это конкретное решение для обеспечения взаимодействие. И я видел злоупотребление тем же медиатором. Как видел злоупотребление декоратором. Любую здравую вещь можно превратить в культ и пихать куда не следует. В некоторым случаях смотришь на код, где декоратор на декораторе, и думаешь, уж лучше бы этот человек писал обычный лапшекод, чем эту жесть. ... |
|||
:
Нравится:
Не нравится:
|
|||
10.11.2020, 14:48 |
|
Иньекция DbContext
|
|||
---|---|---|---|
#18+
hVostt И я видел злоупотребление тем же медиатором. Как видел злоупотребление декоратором. Если в голове пусто, то злоупотребить даже морковным соком можно. ... |
|||
:
Нравится:
Не нравится:
|
|||
10.11.2020, 17:46 |
|
Иньекция DbContext
|
|||
---|---|---|---|
#18+
fkthis hVostt И я видел злоупотребление тем же медиатором. Как видел злоупотребление декоратором. Если в голове пусто, то злоупотребить даже морковным соком можно. Ну вот! К вопросу о transient-ном DbContext, может не надо ломать контекст, чтобы не защащаться от злостных изменений? Как бы если в голове пусто, то хоть привяжи ко лбу пенопласт, помешать разбить лоб это не поможет. ... |
|||
:
Нравится:
Не нравится:
|
|||
10.11.2020, 18:59 |
|
Иньекция DbContext
|
|||
---|---|---|---|
#18+
hVostt Ну вот! К вопросу о transient-ном DbContext, может не надо ломать контекст, чтобы не защащаться от злостных изменений? Ну вот, допустим у меня поверх ЕФ репы. А у репы по самой её сути один вызов - одна транзакция (либо прочитать, либо сохранить). На кой леший мне шарить контекст между ними, если я от этого ничего не выгадываю, а проблем поиметь могу? Расшаренный контекст может иметь смысл, когда действительно с ним, как с UoW работать (таки, правда, и не выяснили, кто этот UoW коммитить будет). ... |
|||
:
Нравится:
Не нравится:
|
|||
10.11.2020, 19:32 |
|
Иньекция DbContext
|
|||
---|---|---|---|
#18+
fkthis Ну вот, допустим у меня поверх ЕФ репы. А у репы по самой её сути один вызов - одна транзакция (либо прочитать, либо сохранить). На кой леший мне шарить контекст между ними, если я от этого ничего не выгадываю, а проблем поиметь могу? Расшаренный контекст может иметь смысл, когда действительно с ним, как с UoW работать (таки, правда, и не выяснили, кто этот UoW коммитить будет). Ну ты хоть покажи каких проблем ты там ожидаешь поиметь. Я в упор не понимаю о каких проблемах ты говоришь. Может ты с ними столкнулся в реале? Потому что сейчас это похоже на проблему преждевременной эякуляции оптимизации. ... |
|||
:
Нравится:
Не нравится:
|
|||
11.11.2020, 01:54 |
|
Иньекция DbContext
|
|||
---|---|---|---|
#18+
hVostt Потому что сейчас это похоже на проблему преждевременной эякуляции оптимизации. У меня все по-скаутски "будь готов" Допустим, у тебя в приложении глобальная переменная, она проблем пока не создавала, но ты видишь, что совершенно спокойно можешь сделать её локальной. Ты это сделаешь, или же это тоже будет "преждевременный рефакторинг"? ... |
|||
:
Нравится:
Не нравится:
|
|||
11.11.2020, 10:12 |
|
Иньекция DbContext
|
|||
---|---|---|---|
#18+
fkthis У меня все по-скаутски "будь готов" Допустим, у тебя в приложении глобальная переменная, она проблем пока не создавала, но ты видишь, что совершенно спокойно можешь сделать её локальной. Ты это сделаешь, или же это тоже будет "преждевременный рефакторинг"? Займусь этим когда в этом возникнет необходимость. Например, глобальная переменная может создать мне проблем для покрытия тестами -- там и сделаю то, что нужно. А просто так заниматься бессмысленной работой смысла не вижу. Твой пример -- яркий. Ты себе что-то вообразил и борешься с этим. Тысячи людей пользуют DbContext в скоупе и он так используется по примерам майкрософт, и всё хорошо. У тебя вдруг с какого-то перепугу в голове стало плохо. Переклинило чтоли? Ну если у тебя дофига свободного времени, и заняться больше нечем, переноси DbContext из скоупа в транзиент. Работа настолько же бессмысленная, насколько и бесполезная и глупая. Но если тебе так спокойней, делай кто мешает ... |
|||
:
Нравится:
Не нравится:
|
|||
11.11.2020, 15:42 |
|
|
start [/forum/topic.php?all=1&fid=18&tid=1354606]: |
0ms |
get settings: |
11ms |
get forum list: |
14ms |
check forum access: |
4ms |
check topic access: |
4ms |
track hit: |
42ms |
get topic data: |
11ms |
get forum data: |
2ms |
get page messages: |
102ms |
get tp. blocked users: |
1ms |
others: | 270ms |
total: | 461ms |
0 / 0 |