|
Иньекция 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 |
|
|
start [/forum/topic.php?fid=18&msg=40015369&tid=1354606]: |
0ms |
get settings: |
10ms |
get forum list: |
14ms |
check forum access: |
3ms |
check topic access: |
3ms |
track hit: |
43ms |
get topic data: |
11ms |
get forum data: |
3ms |
get page messages: |
62ms |
get tp. blocked users: |
1ms |
others: | 15ms |
total: | 165ms |
0 / 0 |