实体框架核心服务的默认生存期 [英] Entity Framework Core service default lifetime

查看:85
本文介绍了实体框架核心服务的默认生存期的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在ASP.NET Core应用程序中,我可以像这样通过DI注册DbContext

In ASP.NET Core application I can register DbContext through DI like this

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

知道它的寿命是什么很有趣?

And it is intersting to know what is its lifetime?

从此处 https://github.com com/aspnet/EntityFramework/blob/f33b76c0a070d08a191d67c09650f52c26e34052/src/Microsoft.EntityFrameworkCore/EntityFrameworkServiceCollectionExtensions.cs#L140 似乎已将其配置为Scoped,这意味着将在每个请求上创建DbContext实例.

From here https://github.com/aspnet/EntityFramework/blob/f33b76c0a070d08a191d67c09650f52c26e34052/src/Microsoft.EntityFrameworkCore/EntityFrameworkServiceCollectionExtensions.cs#L140 it looks like it is configured as Scoped that means DbContext instance is created on every request.

所以问题的第一部分是: 是真的,如果是的话,它的成本是多少?

So first part of the question is: Is it true and if yes, then how costly it is?

第二部分是: 如果我创建了一项服务,它将消耗DbContext,并且打算由Controller消耗,并且将具有用于管理DB中某些实体的API,是否还应该将其注册为Scoped?

And second part is: If I create a service what consumes DbContext, and intended to be consumed by Controllers, and will have an API to manage some entities in DB, should it be registered as Scoped also?

推荐答案

是的,DbContext的默认生存期已确定范围.这是通过这种方式实现的.

Yes, the default life time for DbContext is scoped. This is intended this way.

实例化DbContext非常便宜,并确保您不会使用很多资源.如果您的DbContext的生存期为单身,那么除非您明确禁用跟踪功能,否则您一次读取的所有记录都将被DbContext跟踪.这将需要更多的内存使用量,并且会不断增长.

Instantiating DbContext is pretty cheap and it makes sure that the your do not use to many resources. If you'd have a DbContext with a singleton lifetime, then all records that you read once will be tracked by the DbContext, unless you specifically disable tracking. This will require much more memory usage and it will keep growing.

DbContext轨道越多,性能将越低.这就是为什么您经常看到DbContext仅在using(var context = new AppDbContext())块内使用的原因.

And the more the DbContext tracks, the lower the performance will be. That's why you often see DbContext only used within a using(var context = new AppDbContext()) block.

但是,在Web应用程序中,使用using块是不好的,因为生存期由

In web applications however, using the using block is bad, because the lifetime is managed by the framework and if you dispose it to early the calls after that will fail with an exception.

如果在另一端使用瞬态生存期,则将失去事务"功能.通过作用域,DbContext具有与请求一样长的事务作用域.

If you use transient lifetime on the other side, you will lose the "transaction" functionality. With scoped, the DbContext has a transaction scope that's as long as the request.

如果需要更多细粒度的控制,则必须使用工作单位模式(DbContext已经在使用).

If you need more fine-grained control, you have to use the Unit of Work pattern (which DbContext already kind of utilize).

第二个问题:

如果创建服务,则该服务的生存期必须等于范围之一或更短的寿命(请参阅:作用域或瞬态).

If you create a service, it must have a lifetime that's equal to the one of the scope or shorter (read: Scoped or transient).

如果明确需要更长的服务寿命,则应在服务中注入DbContext工厂服务或工厂方法.

If you explicitly need a longer life-time for a service, you should inject a DbContext factory service or factory method into your service.

您可以使用

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

您的服务可能如下所示:

And your service may look like this:

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();
    }
}

这篇关于实体框架核心服务的默认生存期的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆