C# 中的 dbContext 问题

问题描述 投票:0回答:1

错误消息: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();
c#
1个回答
0
投票

当您尝试执行另一个查询时,您正处于

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 会降低性能。

© www.soinside.com 2019 - 2024. All rights reserved.