實體框架核心服務默認生命週期

asp.net-core entity-framework-core

在ASP.NET Core應用程序中,我可以像這樣通過DI註冊DbContext

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來管理DB中的某些實體,它是否應該註冊為Scoped?

一般承認的答案

是的, DbContext的默認生命DbContext是作用域。這是這樣的。

實例化DbContext非常便宜,它確保您不會使用許多資源。如果你有一個單身生命週期的DbContext ,那麼你讀過的所有記錄都會被DbContext跟踪,除非你專門禁用了跟踪。這將需要更多的內存使用,並將繼續增長。

DbContext跟踪的越多,性能就越低。這就是為什麼你經常看到DbContext只在using(var context = new AppDbContext())塊中使用。

但是在Web應用程序中,使用using塊是不好的,因為生命週期是由框架管理的,如果您將其早期處理,那麼之後的調用將因異常而失敗。

如果您在另一側使用瞬態生命週期,則將失去“事務”功能。使用作用域, DbContext的事務範圍與請求一樣長。

如果你需要更細粒度的控制,你必須使用工作單元模式( DbContext已經使用了它)。

對於你的第二個問題:

如果您創建服務,它的生命週期必須等於範圍或更短的範圍(讀取:Scoped或瞬態)。

如果您明確需要更長的服務生命週期,則應將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();
    }
}

熱門答案

注意:在EF Core 2中,現在有一個新方法AddDbContextPool ,它創建了一個可以重用的上下文池。範圍仍然相同,但實例將“重置”並返回池中。我原本以為“重置”的開銷與創建新的開銷相同,但我想情況並非如此。

如果使用此方法,則在控制器請求DbContext實例時,我們將首先檢查池中是否有可用的實例。請求處理完成後,將重置實例上的任何狀態,並將實例本身返回到池中。+

這在概念上類似於連接池在ADO.NET提供程序中的操作方式,並且具有節省DbContext實例初始化的一些成本的優點。

https://docs.microsoft.com/en-us/ef/core/what-is-new/



Related

許可下: CC-BY-SA with attribution
不隸屬於 Stack Overflow
許可下: CC-BY-SA with attribution
不隸屬於 Stack Overflow