使用 MVVM 和 EF 的 Blazor 服务器端最佳实践

Best practice for Blazor server side using MVVM and EF

我有一个使用 MVVM 和 Entity Framework 的 Blazor 服务器应用程序。我有一个场景,用户可以非常快速地更改搜索条件,从而在第一次调用完成之前对 EF 进行第二次异步调用,从而导致 EF 出现以下异常:“已经有一个与此连接关联的打开的 DataReader,它必须先关闭”。我可以通过使用 IServiceScopeFactory 为 DbContext 创建范围来解决这个问题,但这让我想到,如果我需要解决这个问题,我可能不会以最好的方式进行设置。

我的视图模型是有范围的,它通过构造函数注入获取对我的模型(也有范围)的引用,并且模型也通过构造函数注入获取对 EF 上下文(瞬态)的引用。鉴于我使用的是 Blazor 服务器,在我的场景中,作用域与瞬态并不重要,因为只有一个对象实例请求。所以我的问题是:我是否通过使用 IServiceScopeFactory 适当地阻止了对 EF 的第二次异步调用,还是有更好的方法?

提前感谢您的想法。

在普通的 Blazor 组件中,我只使用 bool 标志,如下所示。我宁愿吃我的键盘也不愿回到 MVVM/MVC,所以这是我能提供给你的最好的:

@inject MyDataService DBS

<input @bind="SearchString"/><button @onclick="DoSearch">Search</button>

@code{
    string SearchString {get; set;} = "";
    bool IsSearching;
    async Task DoSearch (){
         if (!IsSearching){
             IsSearching = true;
             var results = await DBS.DoDataBaseSearch(SearchString);
             IsSearching = false;
         }
    }
}

Microsoft 处理这种情况的最佳做法是使用 DbContextFactory。

ASP.NET Core Blazor Server with Entity Framework Core

.NET 5 之前的版本您必须实现 IDbContextFactory,但如果您将 link 中的版本下拉列表切换为 3.1,则代码在文档中。 .NET 5 及更高版本已为您实现。

Startup.cs
    services.AddDbContextFactory<MyContextClass>(options =>
    {
        options.UseSqlServer(Configuration["MyConnectionString"]);
    }, ServiceLifetime.Transient);

Data access class constructor:
    public MyDataAccessClass(IDbContextFactory<MyContextClass> contextFactory)
    {
        _contextFactory = contextFactory;
    }

Data access method:
    using var context = _contextFactory.CreateDbContext();

然后像往常一样使用上下文。这是一个很好的解决方案,可以控制 Blazor 服务器中 DbContext 实例在持久连接的情况下的生命周期。