Estoy creando una aplicación Blazor del lado del servidor. El siguiente código se encuentra en Startup.cs
.
services.AddDbContext<MyContext>(o => o.UseSqlServer(Configuration.GetConnectionString("MyContext")), ServiceLifetime.Transient);
services.AddTransient<MyViewModel, MyViewModel>();
Y en ViewModel:
public class MyViewModel : INotifyPropertyChanged
{
public MyViewModel(MyContext myContext)
{
_myContext = myContext;
}
public async Task<IEnumerable<Dto>> GetList(string s)
{
return await _myContext.Table1.where(....)....ToListAsync();
}
Y en el archivo de la navaja.
@inject ViewModels.MyViewModel VM
<input id="search" type="text" @bind="search" />
<input id="search" type="button" value="Go" @onclick="SearchChanged" />
@code {
string search = "";
int currentCount = 0;
async void SearchChanged() {
currentCount++;
dtos = GetList(search);
}
}
Sin embargo, ¿a veces se produce el siguiente error al hacer clic en el botón de búsqueda?
System.InvalidOperationException: 'Se inició una segunda operación en este contexto antes de que se completara una operación anterior. Esto generalmente es causado por diferentes subprocesos que usan la misma instancia de DbContext. Para obtener más información sobre cómo evitar problemas de subprocesos con DbContext, consulte https://go.microsoft.com/fwlink/?linkid=2097913 . '
Puede intentar crear un nuevo ámbito para cada solicitud:
public class MyViewModel : INotifyPropertyChanged
{
protected readonly IServiceScopeFactory _ServiceScopeFactory;
public MyViewModel(IServiceScopeFactory serviceScopeFactory)
{
_ServiceScopeFactory = serviceScopeFactory;
}
public async Task<IEnumerable<Dto>> GetList(string s)
{
using (var scope = _ServiceScopeFactory.CreateScope())
{
var referenceContext = scope.ServiceProvider.GetService<MyContext>();
return await _myContext.Table1.where(....)....ToListAsync();
}
}
Aquí Daniel Roth (Gerente de Producto Blazor) hablando sobre el uso de Entity Framework Core con Blazor
Resuelvo el problema, sin embargo, creo que he perdido la Unidad de trabajo porque ahora tengo más de un dbContex:
Constructor:
private AppDbContext _db;
protected override void OnInitialized()
{
_db = new AppDbContext();
var query = _db.Set<Group>().AsQueryable();
}
y luego lo dispongo:
public void Dispose()
{
_db?.Dispose();
}