使用 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 实例在持久连接的情况下的生命周期。
我有一个使用 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 实例在持久连接的情况下的生命周期。