简体   繁体   English

.Net Core DBContext 依赖注入

[英].Net Core DBContext dependency injection

I have refactored my code to try to avoid getting the error below as per the MS Instructions and other posts on this site, it seems to have improved slightly, but if I have multiple button clicks in rapid succession I am still getting the error below :我重构了我的代码,以避免根据MS 说明和本网站上的其他帖子出现以下错误,它似乎略有改进,但如果我快速连续点击多个按钮,我仍然会收到以下错误

A second operation started on this context before a previous operation completed. This is usually caused by different threads using the same instance of DbContext, however instance members are not guaranteed to be thread safe.

startup.cs启动.cs

services.AddDbContext<ApplicationDbContext>(options => options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));

In My Controller:在我的 Controller 中:

readonly RGWIncrementUserActionClicks RGWIncrementClicks = new();
private readonly ApplicationDbContext _context;

public RGWController(IEmailSender emailSender, ApplicationDbContext context)
{
_emailSender = emailSender;
_context = context;
}

public async Task <IActionResult> RGWInsertNewActionNumber(int actionNumber)
{
string userId = ClaimsPrincipalExtensions.GetUserId<string>(User);

await RGWIncrementClicks.UserClick(actionNumber, userId, _context);

return RedirectToAction("RGW");
}

When await RGWIncrementClicks.UserClick(actionNumber, userId, _context);await RGWIncrementClicks.UserClick(actionNumber, userId, _context); is triggered, the UserClick method (Not shown) has a switch statement which can call combinations of other methods to add values to the DB based on the actionNumber parameter passed in.被触发时, UserClick方法(未显示)有一个 switch 语句,它可以调用其他方法的组合,以根据传入的actionNumber参数将值添加到 DB。

I tried with all subsequent methods and calls using await, but still get the multiple thread error.我使用 await 尝试了所有后续方法和调用,但仍然出现多线程错误。 I also tried without them using await and still get the multiple thread error.我也尝试在没有他们的情况下使用 await,但仍然出现多线程错误。

What I don't understand is that await RGWIncrementClicks.UserClick(actionNumber, userId, _context);我不明白的是await RGWIncrementClicks.UserClick(actionNumber, userId, _context); is the point of entry to all subsequent functions that use dbContext, and it uses await , plus it is passing in the injected dbContext for this call instance, so how am I getting a threading error in subsequent functions...they should only trigger a second time after the await here for the entry point completes, indicating all subsequent functions are finished...no?是所有使用 dbContext 的后续函数的入口点,它使用await ,加上它正在为此调用实例传入注入的 dbContext,所以我如何在后续函数中得到线程错误......它们应该只触发一个在这里等待入口点完成后第二次,表明所有后续功能都已完成...不是吗?

Update: I'm just thinking that I don't actually want this to be async, because I want the UI to update on each user click when the RedirectToAction triggers after the Database has been changed.更新:我只是在想我实际上并不希望它是异步的,因为我希望在更改数据库后触发 RedirectToAction 时,UI 在每次用户单击时更新。 So perhaps this is not a thread management issue, instead its a user management issue....I should prevent the user from clicking twice on any button that triggers my RGWInsertNewActionNumber method...所以也许这不是线程管理问题,而是用户管理问题......我应该防止用户在触发我的RGWInsertNewActionNumber方法的任何按钮上单击两次......

Update.2 - I had left this out to save space: Update.2 - 为了节省空间,我把它遗漏了:

public class RGWIncrementUserActionClicks
{
private static readonly IncrementSiteActions _IncrementSiteActions = new();
private static readonly IncrementUserActions _IncrementUserActions = new();

public async Task UserClick(int actionNumber, string userId, ApplicationDbContext _context)
        {
var userActions = await _context.UserEnvironmentalActionCounts.FindAsync(userId);
var siteTotalActions = await _context.SiteEnvironmentalActionCounts.FirstOrDefaultAsync();

siteTotalActions.SiteGlobalWarmingClicks++;

switch (actionNumber)
{
case 1:

if (userActions != null)
{
await _IncrementUserActions.incrementUserActions(userId, userActions => { userActions.ReduceMeat++; userActions.UserReduceMeatCO2Total = userActions.UserReduceMeatCO2Total + 2.0075; }, userActions => { userActions.UserCO2Total = userActions.UserCO2Total + 2.0075; });

if (siteTotalActions != null)
{
await _IncrementSiteActions.incrementSiteActions(siteTotalActions => { siteTotalActions.SiteReduceMeat++; }, true, true, true);
}
else
{
await _context.SiteEnvironmentalActionCounts.AddAsync(new SiteEnvironmentalActionCounts { SiteTotal = 1, SiteGlobalWarmingTotal = 1, SiteReduceMeat = 1, SiteDeforestationTotal = 1, SiteExtinctionTotal = 1 });
}
}
else
{
await _context.UserEnvironmentalActionCounts.AddAsync(new UserEnvironmentalActionCounts { Id = userId, ReduceMeat = 1, UserTotal = 1, UserReduceMeatCO2Total = 2.0075, UserCO2Total = 2.0075 });

if (siteTotalActions != null)
{
await _IncrementSiteActions.incrementSiteActions(siteTotalActions => { siteTotalActions.SiteReduceMeat++; }, true, true, true);
}
else
{
await _context.SiteEnvironmentalActionCounts.AddAsync(new SiteEnvironmentalActionCounts { SiteTotal = 1, SiteGlobalWarmingTotal = 1, SiteReduceMeat = 1, SiteDeforestationTotal = 1, SiteExtinctionTotal = 1 });
}
}
await _context.SaveChangesAsync();
break;

case 2:

...etc.

default:
break;
            }
        }
    }
}

Error details:错误详情:

Microsoft.EntityFrameworkCore.DbContext.SaveChangesAsync(bool acceptAllChangesOnSuccess, CancellationToken cancellationToken)
GatheringForGood.Areas.FunctionalLogic.IncrementUserActions.incrementUserActions(string userId, Action<UserEnvironmentalActionCounts> update, Action<UserEnvironmentalActionCounts> updateUserCO2Total) in IncrementUserActions.cs
+
23. await _context.SaveChangesAsync();
GatheringForGood.Areas.FunctionalLogic.RGWIncrementUserActionClicks.UserClick(int actionNumber, string userId, ApplicationDbContext _context) in RGWIncrementUserActionClicks.cs
+
30. await _IncrementUserActions.incrementUserActions(userId, userActions => { userActions.ReduceMeat++; userActions.UserReduceMeatCO2Total = userActions.UserReduceMeatCO2Total + 2.0075; }, userActions => { userActions.UserCO2Total = userActions.UserCO2Total + 2.0075; });
MyApp.Controllers.ReduceGlobalWarmingController.RGWInsertNewActionNumber(int actionNumber) in ReduceGlobalWarmingController.cs
+
            354. await RGWIncrementClicks.UserClick(actionNumber, userId, _context);
Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor+TaskOfIActionResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, object controller, object[] arguments)
System.Threading.Tasks.ValueTask<TResult>.get_Result()

try to replace尝试更换

private static readonly IncrementSiteActions _IncrementSiteActions = ....
private static readonly IncrementUserActions _IncrementUserActions = ....

with non static ones与非 static 的

private  readonly IncrementSiteActions _IncrementSiteActions = ....
private  readonly IncrementUserActions _IncrementUserActions = ....

I have decided to avoid multiple clicks on the UI layer using javascript. I had a small issue with this, but it was resolved.我已决定使用 javascript 避免多次单击 UI 层。我遇到了一个小问题,但已解决。 More info here if anyone else needs to prevent multiple UI clicks.如果其他人需要防止多次 UI 点击,请在此处获取更多信息。

JS function for a number of elements onclick without using getElementById JS function 对于多个元素 onclick 不使用 getElementById

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 .NET Core 2.1 DbContext ObjectDisposedException 依赖注入 - .NET Core 2.1 DbContext ObjectDisposedException Dependency Injection 具有依赖项注入的 EF 核心 DbContext - EF core DbContext with dependency injection Net Core:使用Xunit为工作单元模式和DBContext执行依赖注入 - Net Core: Execute Dependency Injection with Xunit for Unit of Work Pattern and DBContext 将连接字符串添加到DBContext(NpgSQL,依赖注入,.NET Core) - Adding connection string to DBContext (NpgSQL, Dependency Injection, .NET Core) ASP.NET Core-依赖注入-IdentityServer4 DbContext - ASP.NET Core - Dependency Injection - IdentityServer4 DbContext .NET 核心依赖注入 - 许多数据库,一个 DbContext - .NET Core dependency injection - many databases, one DbContext 如何使用.Net Core 2.1配置依赖项注入的DbContext? - How do I configure a DbContext with dependency injection with .Net Core 2.1? dbcontext 派生自的 Net Core 3.0 依赖注入接口 - Net Core 3.0 dependency injection interface that the dbcontext derived from .NET Core 中的依赖注入 - Dependency injection in .NET Core 在 .NET 核心控制台应用程序中为 EF Core DbContext 服务错误建立依赖注入 - Established dependency injection in .NET Core Console Application for EF Core DbContext Service Error
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM