错误消息:System.InvalidOperationException:'在上一个操作完成之前,在此上下文实例上启动了第二个操作。这通常是由不同的线程同时使用同一个 DbContext 实例引起的。有关如何避免 DbContext 线程问题的更多信息
第二次从数据库获取数据时出现错误
_context.UserPTO.Where(up => up.UserId == user.Id).FirstOrDefault()
在下面的来源
我该怎么做?
private DbContextOptions<DataContext> GetAllOptions()
{
var optionBuilder = new DbContextOptionsBuilder<DataContext>();
optionBuilder.UseSqlServer(AppSettings.ConnectionString);
return optionBuilder.Options;
}
public void UpdatePTO()
{
try
{
using (_context = new DataContext(GetAllOptions()))
{
var users = _context.Users.ToList();
if (users != null && users.Count > 0)
{
foreach (var user in users)
{
var plusPTO = 0.00M;
var workedYear = DateTime.Now.Date.Year - user.StartWorkDate.Date.Year;
switch (workedYear)
{
case int n when (3 < n):
plusPTO = 1.25M;
break;
case int n when (3 < n):
plusPTO = 1.50M;
break;
};
var userPTO = _context.UserPTO.Where(up => up.UserId == user.Id).FirstOrDefault();
if (userPTO != null)
{
userPTO.Pto = userPTO.Pto + plusPTO;
}
var userPTOHistory = new UserPTOHistory
{
UserId = user.Id,
PTOType = "",
UserPTOId = 0,
CurrentPTO = userPTO.Pto,
NeedPTO = 0,
VerifiedType = "Accepted",
CreatedDate = DateTime.Now,
VerifiedDate = DateTime.Now,
CalculatedPTO = userPTO.Pto
};
_context.Add(userPTOHistory);
_context.SaveChangesAsync();
}
}
}
}
catch (Exception)
{
throw;
}
}
// program.cs (cf) 这是一个工人服务项目。 )
using Microsoft.EntityFrameworkCore;
using WorkerService;
using WorkerService.Services;
IHost host = Host.CreateDefaultBuilder(args)
.ConfigureServices((hostContext, services) =>
{
IConfiguration configuration = hostContext.Configuration;
AppSettings.Configuration = configuration;
AppSettings.ConnectionString = configuration.GetConnectionString("DefaultConnection");
var optionBuilder = new DbContextOptionsBuilder<DataContext>();
optionBuilder.UseSqlServer(AppSettings.ConnectionString);
services.AddScoped<DataContext>(d => new DataContext(optionBuilder.Options));
services.AddHostedService<Worker>();
})
.Build();
await host.RunAsync();
当您尝试执行另一个查询时,您正处于
foreach
的中间。您需要启用 MARS 才能正常工作。请参阅文档。
将以下内容添加到您的连接字符串
MultipleActiveResultSets=True
顺便说一句,这是一种很糟糕的获得结果的方法,它有著名的N+1问题。您可以使用连接、导航属性和内联计算做得更好
_context.Users.Select(user =>
new {
user, // user should have PTO navigation property
workedYear = (DateTime.Now.Date.Year - user.StartWorkDate.Date.Year) =>
switch (workedYear)
{
> 3 => 1.25M,
_ => 1.50M,
},
}).ToList();
不清楚您实际对结果做了什么,但重点是让 LINQ 将整个事情翻译成 SQL。
此方法不需要 MARS,MARS 会降低性能。