代码之家  ›  专栏  ›  技术社区  ›  David Thielen

Blazor服务器-短暂使用寿命有多长

  •  0
  • David Thielen  · 技术社区  · 3 年前

    来自阅读 ASP.NET Core Razor component lifecycle 我认为这意味着一个临时服务,每个请求的生存期为,然后可以用于线程不安全的实例(假设我在处理过程中不创建后台线程)。

    是的,有几个步骤,可以在OnInitialized()中编写代码,这需要几秒钟的时间。但从根本上讲,所有的代码都将执行和呈现页面。然后完成,请求就完成了,那个短暂的实例就永远消失了。

    因此,就DbContext而言,再次假设我没有创建任何后台线程,虽然将其作为单例或作用域服务注入是不安全的,但瞬态应该是安全的。还是我错过了什么?

    如果这是真的,有没有办法告诉你 AddDbContextFactory() 提供DbContext作为临时服务?查看相关的类,我没有看到任何设置生成的DbContext生存期的方法。并声明为 [Inject] 在razor文件中意味着作用域或单例生存期,因为它在组件的生存期内存在,而不是组件处理的每个请求。


    使现代化

    我想我把上面的写错了。我担心的是使用:

    [Inject] private UserDbContext UserDbContext { get; set; } = default!;
    

    据我所知,这是由AddDbContextFactory创建的。我相信这给了我一个作用域生存期的DbContext。我担心这个示波器的寿命是有问题的。

    但我看到了 注射 在几乎每一个演示中。

    0 回复  |  直到 3 年前
        1
  •  4
  •   Henk Holterman    3 年前

    重新更新

    我担心这个示波器的寿命是有问题的。

    当然是。这就是添加和使用工厂的全部原因。因此,您不应该注入DbContext。AddDbContextFactory()同时注册工厂和(Scoped)上下文这一事实具有误导性。您仍然没有将上下文与注入一起使用的作用域。

    它的用处有限,可能会有一种情况(例如启动时的DataFeeding),您首先(手动)创建一个Scope,然后将DbContext与注入一起使用。

    但我在几乎每一个演示中都看到了这一点。

    你能链接到几个吗?在页面的持续时间内保留DbContext是可以接受的,但您需要在该页面上使用Dispose()。这就是 OwningComponentBase 是为而发明的。

    将其交给GC也可以,上下文在管理其连接方面是明智的。但是,这仍然是非常草率的。


    有没有办法告诉AddDbContextFactory()将DbContext作为临时服务提供?

    不,DbContext是IDisposable的,所以你不应该想要它。

    DbContextFactory本身是瞬态的,您可以使用它来创建一个DbContext,该DbContext的作用域为 using 条款 using var db = Factory.Create(); 。因此DbContext是资源管理的并且是线程安全的。

    这意味着每个请求的生存期为的瞬态服务可以用于线程不安全的实例

    瞬态对象不与请求绑定,只要您的代码包含对它们的引用,它们就会存在。

    它可以用于非线程安全的状态,但主要用于不需要处理的无状态服务。

        2
  •  2
  •   MrC aka Shaun Curtis    3 年前

    除了@HH的回答。

    据我所知,这个[UserDbContext]是由AddDbContextFactory创建的

    不,如果你注射 UserDbContext 就像你所做的那样,你正在获得 用户数据库上下文 DI容器中定义的服务:无论您在DI设置中设置了什么。

    要从工厂获取工作单元上下文,您需要通过调用 _factory.CreateDbContext() 看见 https://learn.microsoft.com/en-us/ef/core/dbcontext-configuration/#using-a-dbcontext-factory-eg-for-blazor

    在您的示例中:

    [Inject] private IDbContextFactory<TDbContext> _factory { get; set; } = default!;
    

    然后在你的一种方法中这样使用它:

    public Task ExecuteAsync()
    {
        using var dbContext = _factory.CreateDbContext();
    
        // Do some async work on the context
    }
    

    您不需要担心上下文的管理:它们不是由DI管理的。你从工厂里得到一个,使用它,然后通过处理它来释放它。 Dispose 实际上并没有杀死它,它只是把它放回工厂重新使用。

    您是否考虑过将组件中的数据管理和持久性抽象为可测试的数据管道?

    推荐文章