Blazor 服务器:将 EF Core DbContextFactory 与 DbContext 混合使用

Mar*_*ijn 4 c# entity-framework-core asp.net-core blazor .net-5

我正在为现有域层构建 Blazor 服务器前端。这一层提供了各种可注入的服务来对 EF Core 存储库进行修改。为此,服务本身从(标准 Microsoft)DI 容器请求 DbContext。这适用于具有作用域 DbContext 实例的常规 MVC.NET/Razor 页面,但如文档所述,这在 Blazor 中存在问题。在 Blazor 服务器应用程序中,我们希望使用 DbContextFactory 来为操作生成短期 DbContext 实例。

在同一个应用程序中同时拥有 DbContext 和 DbContextFactory 没有问题,但我很难理解如何调整我的服务。或者,如果我什至需要?为了说明,这是当前的代码:

我的页面:

@page “/items”
@inject ItemService ItemService

// somewhere in the code
    ItemService.DoOperation(…)
Run Code Online (Sandbox Code Playgroud)

我的服务

@page “/items”
@inject ItemService ItemService

// somewhere in the code
    ItemService.DoOperation(…)
Run Code Online (Sandbox Code Playgroud)

启动.cs:

class ItemService
{
    public ItemService(MyDbContext myDbContext)
    {
        …
    }

    public bool DoOperation(…)
    {
        …
        _myDbContext.SaveChanges();
    }
}
Run Code Online (Sandbox Code Playgroud)

我已经根据此答案中给出的示例更改了 DbContext 的生命周期,到目前为止我还没有能够创建任何问题,但我不完全理解这里的生命周期问题。如何设计我的服务以明显的方式在 Blazor 和 MVC/Razor Pages 应用程序中运行良好?

Gri*_*lly 5

在典型的 MVC 应用程序中,一个请求代表一个工作单元。DbContext 作为范围服务生成并通过构造函数注入。这可以。

另一方面,在 Blazor 服务器中,一个请求不再代表单个工作单元。第一个请求创建一个电路,这意味着注入的任何范围服务都将具有此处所述的生命周期。

在 Blazor 服务器应用中,工作单元是 SignalR 消息。(例如,单击按钮可向数据库添加新行)。因此,直接注入您的上下文不是要走的路

这就是 Blazor Server 具有IDbContextFactory<T>. 像这样初始化它:

services.AddDbContextFactory<DbContext>(options =>
                options.UseSqlServer(
                    Configuration.GetConnectionString("WebDB")));
Run Code Online (Sandbox Code Playgroud)

在您的 Razor 组件(绑定到 Blazor 应用程序)中,您可以像这样使用它:

private readonly IDbContextFactory<DbContext> factory;

public Component(IDbContextFactory<DbContext> f)
{
    factory = f;
}

public void Click()
{
    using(DbContext cnt = factory.CreateDbContext())
    {
    // Your code here
    }
}
Run Code Online (Sandbox Code Playgroud)

这将在此处进一步解释。

文档:带有 Entity Framework Core (EFCore) 的 ASP.NET Core Blazor 服务器

  • 是的,这就是我现在正在做的事情,以便从 Blazor 直接访问 EF Core。问题在于我当前使用的现有服务注入 DbContext 而不是 DbContextFactory。这肯定是一个常见问题,但我看到没有人谈论它。 (4认同)
  • 在我看来,直接从组件访问 DbContext 仅适用于非常简单的用例。在复杂的体系结构中,有多个服务相互调用,每个服务都需要访问*相同的* DbContext 实例(例如 BlogService 调用 PostService),这种方法不起作用。所有服务*必须*接收相同的 DbContext 实例才能正常工作。我一直在网上寻找可能的解决方案,但没有找到任何有用的东西。它是最基本的架构方法之一,但还没有任何真正的解决方案。 (2认同)

Hen*_*man 1

问题是可传递的:您的服务依赖于应限定范围的资源,并且只有当您将这些服务也注册为限定范围时才有效。但你不能。

正确的方法是将您的服务重写为 DbContext per Operation 模型,并注入 DbContextFactory。

看起来您已经有了一个混合模型(每个操作都有一个 SaveChanges,它们实际上是一个 UoW)。

当您不想进行这些更改时,您可以通过将 DbContext 注册为 Transient 来避开。这感觉很糟糕,但它旨在快速释放底层连接。所以这并不是看起来那样的资源泄漏。


归档时间:

查看次数:

360 次

最近记录:

5 年,3 月 前