Срок службы службы ядра Entity Framework по умолчанию

В приложении ASP.NET Core я могу зарегистрировать DbContext через DI, как это

services.AddDbContext<Models.ShellDbContext>(options => options.UseNpgsql(connection));

И интересно знать, какова его продолжительность жизни?

Отсюдаhttps://github.com/aspnet/EntityFramework/blob/f33b76c0a070d08a191d67c09650f52c26e34052/src/Microsoft.EntityFrameworkCore/EntityFrameworkServiceCollectionExtensions.cs#L140 похоже, он настроен как Scoped, что означает, что экземпляр DbContext создается при каждом запросе.

Итак, первая часть вопроса: правда ли это, и если да, то насколько это дорого?

И вторая часть: если я создаю сервис, который использует DbContext и предназначен для использования контроллерами, и будет иметь API для управления некоторыми объектами в БД, должен ли он быть зарегистрирован как Scoped?

Ответы на вопрос(3)

это - то, что я изучил. И это от ленивой преданности KISS. Я избежал других сложностей и решил свою проблему преждевременного EF Core. DbContext избавляется от проблем с пулами, областями и т. Д. Я просто собирал POC без учета асинхронных возвращаемых значений, связанных из Control, передаваемых в хранилище. и так далее, которые все по существу возвращали «пустоту», т. е. буквально в единственном числе, «Задача». Это заставило итерации среди моих членов DbContext в более низких подпрограммах необъяснимым образом избавиться от базового DbContext. Все, что мне нужно было сделать, это заставить каждый асинхронный метод возвращатьTask<whatever return> ценность и все работало. EF Core не любит асинхронные пустые возвращаемые значения.

Решение Вопроса

DbContext ограничен Это предназначено таким образом.

ИнстанцированиеDbContext это довольно дешево, и это гарантирует, что вы не используете много ресурсов. Если бы у вас былDbContext с единственным временем жизни, все записи, которые вы прочитали один раз, будут отслеживатьсяDbContext, если вы специально не отключите отслеживание. Это потребует гораздо большего использования памяти и будет продолжать расти.

И чем больше темDbContext треки, тем ниже будет производительность. Вот почему вы часто видитеDbContext используется только вusing(var context = new AppDbContext()) блок.

Однако в веб-приложениях, используяusing блок плох, потому что время жизни управляетсяфреймворк и если вы настроите его на ранние вызовы, то после этого произойдет сбой с исключением.

Если вы используете временное время жизни на другой стороне, вы потеряете функциональность «транзакции». С областью,DbContext имеет объем транзакции, равный запросу.

Если вам нужен более детальный контроль, вы должны использовать шаблон единиц работы (которыйDbContext уже вроде как использую).

Для вашего второго вопроса:

Если вы создаете сервис, у него должен быть срок службы, равный сроку службы или меньше (читай: Scoped или transient).

Если вам явно требуется более длительный срок службы, вы должны ввестиDbContext Фабричный сервис или фабричный метод к вашим услугам.

Вы можете сделать это с помощью чего-то вроде

services.AddTransient<Func<AppDbContext>>( (provider) => new Func<MyDbContext>( () => new AppDbContext()));
services.AddSingleton<IMySingletonService, MySingletonService>();

И ваш сервис может выглядеть так:

public class MySingletonService : IMySingletonService, IDisposable
{
    private readonly AppDbContext context;

    public MySingletonService(Func<AppDbContext> contextFactory)
    {
        if(contextFactory == null)
            throw new ArgumentNullException(nameof(contextFactory));

        // it creates an transient factory, make sure to dispose it in `Dispose()` method.
        // Since it's member of the MySingletonService, it's lifetime
        // is effectively bound to it. 
        context = contextFactory();
    }
}
 Alex Gurskiy18 июл. 2018 г., 03:02
Мои 5 центов об отслеживании на избранных. Если вы не хотите отслеживать коллекции ваших сущностей, вы можете просто использовать метод AsNoTracking (). Я не уверен на 100%, но теоретически это должно сэкономить ресурсы и немного сократить время запроса.
 Tseng30 мая 2016 г., 15:54
Если вы вводите напрямуюDbContext тогда нет, не избавляйся. Обратите внимание, что в своем ответе я передаю делегатаFunc<AppDbContext> contextFactory где делегаты создают новый экземпляр фабрики при каждом обращении к нему
 Joe Audette29 мая 2016 г., 17:28
в веб-приложении это действительно контроллер, который управляет временем жизни? или это DI, который располагает объекты, определенные для каждого запроса, в конце запроса? Я хотел бы понять это лучше
 Tseng29 мая 2016 г., 18:31
Виноват. Я хотел сказать рамки. Есть фабрика контроллеров (IControllerFactory, увидетьgithub.com/aspnet/Mvc/blob/dev/src/... для реализации по умолчанию) в этоCreateControllerметод, который создает контроллер и располагает его и располагает его, и его зависимости вReleaseController() метод. Также посмотрите эту проблему GitHub на более подробную информацию о внутренней работе и почему она работает таким образом:github.com/aspnet/Mvc/issues/3727
 Joe Audette30 мая 2016 г., 13:09
Благодарю. если у меня есть репозиторий, который принимает DbContext в своем конструкторе, и он реализует IDisposable, должен ли он вызывать dispose на DbContext из своего собственного метода dispose? Я заметил, что EF UserStore for Identity не вызывает dispose для dbcontext, но мне кажется, что это неправильно, поэтому я пытаюсь понять, почему они этого не сделали

AddDbContextPool который создает пул контекстов, которые можно использовать повторно. Область действия остается прежней, но экземпляр будет «сброшен» и возвращен в пул. Я бы подумал, что издержки «перезагрузки» будут такими же, как просто создание новой, но я думаю, это не так.

Если этот метод используется, в то время, когда контроллер запрашивает экземпляр DbContext, мы сначала проверим, есть ли экземпляр в пуле. После завершения обработки запроса любое состояние экземпляра сбрасывается, а сам экземпляр возвращается в пул.

Это концептуально аналогично тому, как работает пул соединений в поставщиках ADO.NET, и имеет преимущество, заключающееся в экономии некоторых затрат на инициализацию экземпляра DbContext.

https://docs.microsoft.com/en-us/ef/core/what-is-new/ef-core-2.0#high-performance

 Simon_Weaver02 янв. 2018 г., 10:15
Угадаете, может быть, это функция OnModelCreating, которая может занять много времени с большой базой данных?

Ваш ответ на вопрос