【问题标题】:System.InvalidOperationException: when saving data to my databaseSystem.InvalidOperationException:将数据保存到我的数据库时
【发布时间】:2019-06-11 19:00:59
【问题描述】:

ASP.Net 核心 blazor 应用程序。当页面首次打开时,它会从数据库中提取维修订单列表并将其显示在页面上。这很好用。

数据表有一列带有“编辑”按钮。当您编辑数据时,会弹出一个模式并显示 RO 信息供某人编辑。

我的问题是当我点击“保存”时,出现以下错误。

错误代码:

System.InvalidOperationException: '第二个操作开始于此 前一个操作完成之前的上下文。这通常是由于 但是,不同的线程使用相同的 DbContext 实例 不保证实例成员是线程安全的。这也可以 是由在客户端上评估的嵌套查询引起的,如果这是 案例重写查询避免嵌套调用。'

值得注意的是,此功能运行良好,但我不知道我做了什么更改使其失败。 OnInitAsync() 方法:

protected override async Task OnInitAsync()
    {
        await LoadData();        
    }

加载所有数据的方法:

protected async Task LoadData()
    {
        _repairOrders = await Task.Run(() => RepairOrderService.GetAllRepairOrders().ToArray());
        _vehicleLocations = await Task.Run(() => VehicleLocationService.GetAllLocations().ToArray());
        _repaitStages = await Task.Run(() => RepairStageService.GetAllRepairStages().ToArray());
        _employees = await Task.Run(() => EmployeeService.GetAllEmployees().ToArray());
    }

调用方法来保存数据。

protected async Task SaveRepairOrder()
    {
        if (ro.Id != 0)
        {
            await Task.Run(() =>
            {
                RepairOrderService.EditRepairOrder(ro);
            });
        }
        else
        {
            await Task.Run(() =>
            {
                RepairOrderService.CreateRepairOrder(ro);
            });
        }
        this.isAdd = false;
        await LoadData();
    }

这是我的数据访问层类中引发错误的方法。

//Get all repair order details as a list
        public List<RepairOrder> GetAllRepairOrders()
        {
            try
            {
                return db.RepairOrder.ToList();
            }
            catch
            {
                throw;               
            }
        }

我在问题开始后使 LoadData() 方法异步。谁能看到我错过了什么?

**** 更新 ******** 我更改了“services.AddSingleton();”到“services.AddTransient();”它似乎正在工作。我需要深入研究并尝试确定这是否是我一开始就应该这样做的方式!

【问题讨论】:

  • 不要把它们放在task.run中。
  • 如果我只使用'await RepairOrderService.GetAllRepairOrders().ToArray();'我收到错误消息:“RepairOrder[]”不包含“GetAwaiter”的定义.....我的运行不是异步的,但这个问题开始了。
  • @EdPlunkett 抱歉没有想到!固定
  • 您尚未显示创建db 的位置,但最佳做法是在您需要它们的位置打开连接,并在运行查询后立即处理它们。最好将其包含在 using 块中。不用担心效率低下,框架会为你维护一个连接池,并在连接可用时立即重用。
  • @iakobski 我使用了 Entity 的 Scaffold-dbcontext 工具。上下文类连接到数据库。有数据访问层类调用上下文,最后我的页面代码调用数据服务调用数据访问类。

标签: c# entity-framework blazor


【解决方案1】:

正如错误提到的,这里发生的事情是其他线程已经在使用上下文,因为您的方法正在尝试使用它。

将注册更改为 Transient 有效,因为该实例不再共享...每次获得它,它都会是一个新的...这有一些缺点,例如,如果您尝试“加入”两个 @ 987654321@ 它会失败...内存消耗也应该会增加。

现在,对于您的问题,您必须调试代码流,因为显然,当您的代码进入 LoadData 方法时,先前启动的操作正在后台运行!所以“Task.Run”实际上与错误无关......如果你删除它,你应该得到同样的错误......

你可以做一些事情来验证这个假设是在加载数据之前添加大约一两秒的延迟(等待 Task.Delay(2000);)......这应该足以让其他操作完成,释放方法的上下文

【讨论】:

    猜你喜欢
    • 2012-05-19
    • 1970-01-01
    • 2019-11-22
    • 1970-01-01
    • 1970-01-01
    • 2012-07-21
    • 2019-03-31
    相关资源
    最近更新 更多