【发布时间】:2022-01-08 15:35:30
【问题描述】:
我对依赖注入中的作用域概念有疑问。我已将我的数据库上下文注册为范围,并且我使用异步方法将用户活动保存在表中,而不使用“等待”。
// In Startup:
services.AddScoped<IDbContext, StorageSystemDbContext>();
services.AddScoped<IUserActivityService,UserActivityService>();
// In UserActivityService:
public async void LogUserActivityAsync(string controllerName, string actionName, ActionType actionType = ActionType.View, string data = "", string description = "")
{
await InsertAsync(new UserActivity
{
ControllerName = controllerName,
ActionName = actionName,
ActionType = actionType,
CreatedDateTime = DateTime.Now,
Description = description,
UserId = (await _workContext.CurrentUserAsync())?.Id
});
}
//In Controller:
_userActivityService.LogUserActivityAsync(CurrentControllerName, CurrentActionName,data);
当我立即两次调用 same 操作时出现以下错误:
InvalidOperationException:在前一个操作完成之前,在此上下文中启动了第二个操作。这通常是由不同的线程同时使用同一个 DbContext 实例引起的。有关如何避免 DbContext 线程问题的更多信息,请参阅https://go.microsoft.com/fwlink/?linkid=2097913。
我预计第二个请求会创建一个新的数据库上下文,具体取决于数据库上下文依赖注册的类型,但根据这个错误,没有为第二个请求创建一个新的上下文,而是使用了前一个。
这是什么原因?
我在 .Net Core 5 中使用 Asp Net.Core MVC 和 EF
【问题讨论】:
-
你在使用 Blazor 吗?否则,作为 Scoped 依赖项,您将为每个 Http 请求获得一个新的 DbContext。
-
我在 .net core 5 中使用 Asp Net.core mvc 和 EF
-
你使用了 async void。这是一个巨大的红旗。在极少数情况下这样做是有意义的。这不是其中的一个。我建议你 watch Nick Chapsas video 这解释了为什么这很糟糕,和/或阅读 Stephen Cleary's article。
-
我不希望程序线程等待这个方法完成。将 void 改为 Task 会解决问题吗?
-
不等待
async呼叫的唯一真正理由是您打算在类似 WaitAll() 之后继续。它不打算用作“一劳永逸”的后台线程。认真地阅读所提供的推荐材料。有非常充分的理由不以这种方式处理它。
标签: entity-framework asp.net-core dependency-injection