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

В принципе, не могу вспомнить, чтобы у меня случались какие-то проблемы с этим, но не оставляет ощущение, что в этом заложено что-то недоброе. Scoped компонент в ASP.NET Core это объект глобальный для всего HTTP request, т.е. со всеми возможными граблями глобального объекта (сторонние эффекты).

Я однажды предложил вместо DbContext инжектить его фабрику, но у всех, разумеется, тут же полыхнуло, типа: "Еще наши прадеды инжектили DbContext, а ты тут собрался оскорбить их память и могилы обосс..ть". Вот мне и интересно узнать - кто-нибудь делает инъекцию DbContext не напрямую?
...
Рейтинг: 0 / 0
Иньекция DbContext
    #40015328
handmadeFromRu
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ну я пробовал раньше делать дженерик репо + uow и ощущал что это велик какой то.
фабрика ты вроде как говоришт дело но тогда ты будешь отвечать за закрытие и обслуживание и где гарантиии что кто то из твоих прогеров не забудет про закрытие ручное( кто создал тот и мочит хороший тон) поэтому когда я пишу код лично я стараюсь прям в коде сделать ограничение по использованию чего либо чтоб след прогер минимально в ногу выстрелил, конечно эт не отменяет что можно удалить код. если мы говорим в концепции di то скоуп вполне себе модель.
если так судить то у тебя все что в скоупе реквеста "глобальное"
...
Рейтинг: 0 / 0
Иньекция DbContext
    #40015332
fkthat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
handmadeFromRu
тогда ты будешь отвечать за закрытие и обслуживание

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

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

Нет, если фабрика будет работать через тот же DI, то при выходе из скоупа все что она насоздавала будет тоже диспозиться. В принципе, есть-то опция, чтобы регистрировать DbContext как transient, но на существующем проекте это как бы слишком уж глобаное изменение и делать его рисковано.

где эт написано что оно высвободится то? что то новая инфа прям.
...
Рейтинг: 0 / 0
Иньекция DbContext
    #40015338
handmadeFromRu
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
fkthat

Да как бы нет, любой объект DI действительно принадлежить какому-либо скоупу, но ведь если он зареган как transient, то для каждой инъекции создается новый инстанс, так что никакой глобальности - каждый зависимый объект получит свой собственный экземпляр зависимости.

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

Все что создается через ДиАй диспозится автоматически когда диспозится его скоуп. Это же испокон веков во всех контейнерах так. Сам проверь, убедись, если хочешь. И транзиент тоже.
...
Рейтинг: 0 / 0
Иньекция DbContext
    #40015356
fkthat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
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.
using System;
using Microsoft.Extensions.DependencyInjection;

ServiceCollection services = new();
services.AddTransient<Foo>();
using var provider = services.BuildServiceProvider();

using (var scope = provider.CreateScope())
{
    for (var i = 0; i < 7; i++)
    {
        scope.ServiceProvider.GetRequiredService<Foo>();
    }
}

public class Foo : IDisposable
{
    public void Dispose()
    {
        Console.WriteLine("Bye-bye!");
    }
}


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

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

Все что создается через ДиАй диспозится автоматически когда диспозится его скоуп. Это же испокон веков во всех контейнерах так. Сам проверь, убедись, если хочешь. И транзиент тоже.

погоди ты говорил через фабрику а не di. если как к примеру в dryioc заюзать фитчу верни мне фабрику объектов да вызоветься а если ты нашлепал фабрику типо
Код: c#
1.
2.
3.
4.
5.
6.
7.
 public class FooFabric
        {
            public Foo Create()
            {
                return new Foo();
            }
        }


то нет
с transient был не прав. в голове шелкнуло наверное изза привычки dryioc , он подефлту Dispose интерфейсы не позволяет регистрировать как Transient.
...
Рейтинг: 0 / 0
Иньекция DbContext
    #40015374
Фотография hVostt
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
fkthat
Стандартный паттерн использования DbContext в ASP.NET Core это его иньекция туда где он нужен. Сам DbContext при этом принято регистрировать как scoped (так по умолчанию).

В принципе, не могу вспомнить, чтобы у меня случались какие-то проблемы с этим, но не оставляет ощущение, что в этом заложено что-то недоброе. Scoped компонент в ASP.NET Core это объект глобальный для всего HTTP request, т.е. со всеми возможными граблями глобального объекта (сторонние эффекты).

Я однажды предложил вместо DbContext инжектить его фабрику, но у всех, разумеется, тут же полыхнуло, типа: "Еще наши прадеды инжектили DbContext, а ты тут собрался оскорбить их память и могилы обосс..ть". Вот мне и интересно узнать - кто-нибудь делает инъекцию DbContext не напрямую?


Ну вообще в рамках scoped (запроса) один экземпляр контекста -- это хорошо. Ибо транзакционность, ибо кеш первого уровня, и возможность на нескольких уровнях работать с полученным ентити. В одном месте получили, в другом записали.

Если у тебя будет transient, ты огребёшь проблем и потерю в производительности.

Другое дело, фабрика позволяет иметь более одного DbContext-а. Но это решается на уровне абстракции.

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


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

Врят ли. Кстати, по производительности. Если ты сделаешь подряд запросы, типа
Код: c#
1.
2.
var client1 = _db.Clients.SingleOrDefault(c => c.Id == 42);
var client2 = _db.Clients.SingleOrDefault(c => c.Id == 42);


То объект тебе вернет один и тот же, но у тебя все равно будет два запроса к БД, т.е. кеша все равно нет.

hVostt
У нас на одном проекте есть инъекция DbContext через авто-фабрику IIndex (Autofac)

Всегда нравилась эта его фича. Особенно с инжектом Func<IService> - там даже фабрики в большинстве случаев не надо.
...
Рейтинг: 0 / 0
Иньекция DbContext
    #40015383
fkthat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
hVostt
DbContext как бы по природе не совсем транзиентный :)

Практически все сценарии работы с ним в ASP.NET - "запросил -> изменил -> сохранил", а потом он уже становится не нужен. Если какая-то десктопная аппликуха, то там вполне может быть и по другому, но в вебе само по себе все считай транзитивное из-за его stateless натуры.
...
Рейтинг: 0 / 0
Иньекция DbContext
    #40015385
Фотография hVostt
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
fkthat
Врят ли. Кстати, по производительности. Если ты сделаешь подряд запросы, типа
Код: c#
1.
2.
var client1 = _db.Clients.SingleOrDefault(c => c.Id == 42);
var client2 = _db.Clients.SingleOrDefault(c => c.Id == 42);



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

Если у тебя прокси-ентити, то обращения по навигационной сущности не будут запрошены дважды.
Если ты обращаешься к справочникам нормальным образом через Find(...), то каждая единица будет запрошена только один раз, а загруженные ранее в любом качестве не будут запрошены из БД, а взяты из кеша.

Если у тебя сложная логика работы с сущностями, то кеш довольно большую роль играет.

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

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


Не вопрос, всё верно. Но в рамках запроса у тебя может быть несколько действий с БД.
ДбКонтекст это же не только транслятор LINQ=>SQL.
Если тебе именно транлятор нужен, то EF выбор так себе.
...
Рейтинг: 0 / 0
Иньекция DbContext
    #40015387
Фотография hVostt
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
fkthat,

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

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

Почему?
...
Рейтинг: 0 / 0
Иньекция DbContext
    #40015427
vb_sub
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Фабрика по определению решает совершенно другие проблемы-неопределенность получения конкретного типа DbContext в рантайме.
Вышеуказанной проблемы у ТС нет. Инъекция фабрики, которая выдаст DbContext вместо самого DbContext это просто добавление еще ненужного слоя абстракции.
Хотя возможно ТС хочет, чтобы фабрика выдавала или Scoped или Transient экземпляр? Просьба более подробно раскрыть этот момент.
...
Рейтинг: 0 / 0
Иньекция DbContext
    #40015430
fkthat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
hVostt
Не вопрос, всё верно. Но в рамках запроса у тебя может быть несколько действий с БД.
ДбКонтекст это же не только транслятор LINQ=>SQL.
Если тебе именно транлятор нужен, то EF выбор так себе.


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

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

В общем, глобальный объект это глобальный объект, от того что его назвали красивым словом "scoped" он глобальным быть не перестал, разве что его "глобальность" несколько ограничили.
...
Рейтинг: 0 / 0
Иньекция DbContext
    #40015431
fkthat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
vb_sub
Хотя возможно ТС хочет, чтобы фабрика выдавала или Scoped или Transient экземпляр? Просьба более подробно раскрыть этот момент.

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

Я бы лучше сказал "в рамках вызова сервиса". Потому что если несколько взаимосвязанных запросов раскиданы по нескольким сервисам, то это вообще какой-то говнодизайн, нарушается весь loose coupling. А если в рамках одного вызова сервиса, то какие проблемы - получи контекст, сделай там хоть стопятьсот запросов и изменений, потом все одним разом сохрани - обычный Unit of work. И вот, кстати цикл работы с UoW (загрузи -> измени -> сохрани) это по сути отдельная логическая транзакция (не зря ведь его назвали "unit"). И существует очень общее правило: "при завершении (коммит/роллбек) транзакция забывает свое состояние". Т.е. любая транзакция никогда не должна использовать данные полученные в другой транзакции. А шейринг контекста между сервисами это правило нарушает.
...
Рейтинг: 0 / 0
Иньекция DbContext
    #40015438
fkthat
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
handmadeFromRu
тот не ловкий момент с трансет я думал чутка не так но работает все) капец как стыдно

Тут, на самом деле, есть еще подводный камень, про который надо помнить - даже транзитивный объект живет все время жизни скоупа в котором он создан. В ASP.NET это проблем не создает, т.к. сами скоупы все короткоживущие, но, скажем, в каком-нибудь десктопном приложении это следует учитывать.
...
Рейтинг: 0 / 0
Иньекция DbContext
    #40015440
handmadeFromRu
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
fkthat
handmadeFromRu
тот не ловкий момент с трансет я думал чутка не так но работает все) капец как стыдно

Тут, на самом деле, есть еще подводный камень, про который надо помнить - даже транзитивный объект живет все время жизни скоупа в котором он создан. В ASP.NET это проблем не создает, т.к. сами скоупы все короткоживущие, но, скажем, в каком-нибудь десктопном приложении это следует учитывать.

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


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