EF error: A second operation started on this context before a previous asynchronous operation completed
EF error: A second operation started on this context before a previous asynchronous operation completed
我是 Blazor 的新手并且在服务器端 Blazor 应用程序 (.NET 5) 中工作有以下内容:
我有以下表格:
<EditForm Model="@MyObject" OnValidSubmit="Submit">
<DataAnnotationsValidator />
<ValidationSummary />
<InputText id="name" @bind-Value="MyObject.Name" />
<button type="submit">Submit</button>
</EditForm>
后面的代码:
public MyObject MyObject { get; set; } = new MyObject();
[Inject]
private IMyObjectService myObjectService { get; set; }
[Inject]
private NavigationManager navigationManager { get; set; }
void Submit()
{
var created = myObjectService.CreateMyObject(MyObject);
if (created != null)
{
navigationManager.NavigateTo("myobjects/manage");
} else
{
// do something
}
}
回购:
private readonly ApplicationDbContext _dbContext;
public MyObjectRepo(ApplicationDbContext dbContext)
{
_dbContext = dbContext;
}
public async Task<MyObject> CreateMyObject(MyObject MyObject)
{
_dbContext.Add(MyObject);
await _dbContext.SaveChangesAsync();
return MyObject;
}
public async Task<bool> DoesMyObjectExistByName(string name)
{
var exists = await _dbContext.MyObjects.AnyAsync(x => x.Name == name);
if (exists) return true;
return false;
}
然后我有一个 MyObjectService
:
private readonly IMyObjectRepo _myObjectRepo ;
public MyObjectService(IMyObjectRepo myObjectRepo )
{
_myObjectRepo = myObjectRepo;
}
public async Task<MyObject> CreateMyObject(MyObject MyObject)
{
if (MyObject == null) throw new ArgumentNullException("MyObject cannot be null.");
// THIS LINE THROWS THE EF ERROR
var exists = await _myObjectRepo.DoesMyObjectExistByName(MyObject.Name);
if (!exists)
{
return await _myObjectRepo.CreateMyObject(MyObject);
} else
{
return null;
}
}
但是每次我调用服务到 createMyObject 方法时,EF 都会抛出一个错误:
Error: System.InvalidOperationException: A second operation was
started on this context before a previous operation completed. This is
usually caused by different threads concurrently using the same
instance of DbContext.
在 Startup.cs (.NET 5) 中,我配置了瞬态生命周期。
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("Default")),
ServiceLifetime.Transient);
services.AddAutoMapper(typeof(Startup));
services.AddScoped<IMyObjectRepo, MyObjectRepo>();
services.AddScoped<IMyObjectService, MyObjectService>();
我认为我使用了 async/await 和线程安全的所有正确语法,有什么想法吗?
我自己不熟悉 Blazor
,但我认为您的 Submit
方法应该类似于 -
async void Submit()
{
var created = await myObjectService.CreateMyObject(MyObject);
if (created != null)
{
navigationManager.NavigateTo("myobjects/manage");
} else
{
// do something
}
}
基本上,您缺少 async/await 个关键字。
我是 Blazor 的新手并且在服务器端 Blazor 应用程序 (.NET 5) 中工作有以下内容:
我有以下表格:
<EditForm Model="@MyObject" OnValidSubmit="Submit">
<DataAnnotationsValidator />
<ValidationSummary />
<InputText id="name" @bind-Value="MyObject.Name" />
<button type="submit">Submit</button>
</EditForm>
后面的代码:
public MyObject MyObject { get; set; } = new MyObject();
[Inject]
private IMyObjectService myObjectService { get; set; }
[Inject]
private NavigationManager navigationManager { get; set; }
void Submit()
{
var created = myObjectService.CreateMyObject(MyObject);
if (created != null)
{
navigationManager.NavigateTo("myobjects/manage");
} else
{
// do something
}
}
回购:
private readonly ApplicationDbContext _dbContext;
public MyObjectRepo(ApplicationDbContext dbContext)
{
_dbContext = dbContext;
}
public async Task<MyObject> CreateMyObject(MyObject MyObject)
{
_dbContext.Add(MyObject);
await _dbContext.SaveChangesAsync();
return MyObject;
}
public async Task<bool> DoesMyObjectExistByName(string name)
{
var exists = await _dbContext.MyObjects.AnyAsync(x => x.Name == name);
if (exists) return true;
return false;
}
然后我有一个 MyObjectService
:
private readonly IMyObjectRepo _myObjectRepo ;
public MyObjectService(IMyObjectRepo myObjectRepo )
{
_myObjectRepo = myObjectRepo;
}
public async Task<MyObject> CreateMyObject(MyObject MyObject)
{
if (MyObject == null) throw new ArgumentNullException("MyObject cannot be null.");
// THIS LINE THROWS THE EF ERROR
var exists = await _myObjectRepo.DoesMyObjectExistByName(MyObject.Name);
if (!exists)
{
return await _myObjectRepo.CreateMyObject(MyObject);
} else
{
return null;
}
}
但是每次我调用服务到 createMyObject 方法时,EF 都会抛出一个错误:
Error: System.InvalidOperationException: A second operation was started on this context before a previous operation completed. This is usually caused by different threads concurrently using the same instance of DbContext.
在 Startup.cs (.NET 5) 中,我配置了瞬态生命周期。
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("Default")),
ServiceLifetime.Transient);
services.AddAutoMapper(typeof(Startup));
services.AddScoped<IMyObjectRepo, MyObjectRepo>();
services.AddScoped<IMyObjectService, MyObjectService>();
我认为我使用了 async/await 和线程安全的所有正确语法,有什么想法吗?
我自己不熟悉 Blazor
,但我认为您的 Submit
方法应该类似于 -
async void Submit()
{
var created = await myObjectService.CreateMyObject(MyObject);
if (created != null)
{
navigationManager.NavigateTo("myobjects/manage");
} else
{
// do something
}
}
基本上,您缺少 async/await 个关键字。