【问题标题】:Several threads working on same table (read+write) with entity framework core多个线程在具有实体框架核心的同一张表(读+写)上工作
【发布时间】:2022-04-11 22:20:56
【问题描述】:

我需要从多个线程读取/写入任务表。这些线程是任务表的消费者,并从中删除和更新任务。他们更新表以“拥有”一项任务,并在完成执行后将其从表中删除。

我一直在阅读当一些线程与实体框架核心在同一个表上工作时可能发现的怪癖,我注意到 DbContext 不是线程保存的。所以,我必须每个线程都有一个 DbContext。

我预见到的问题是当一个线程更新一行以将其分配给队列但同时另一个线程试图将该任务分配给另一个队列时会发生什么。

有没有锁定行?这是实体框架在访问行时在后台执行的操作吗?在对所有系统进行编码之前,我想对问题进行一些概述。

P.D.我正在使用带有 pomelo 驱动程序的 mysql 后端。

【问题讨论】:

  • 您使用的是什么数据库?在 Oracle 中,您可以执行 SELECT FOR UPDATE 锁定记录。我假设其他数据库也有类似的东西。
  • 我对 EF 不太熟悉,但 MySQL 有 SELECT FOR UPDATE 功能。如果您需要更具体的帮助,您需要提供有关您的实施的更多详细信息。这个问题可能是一个很好的起点:stackoverflow.com/questions/37984312/…
  • 从“不同的线程”读取和写入怎么样,而是有一个读取器/写入器(可能配备某种线程安全的队列机制),通过它所有读/写都必须通过。这将大大简化事情,并在一定程度上减少射中自己脚的机会。
  • @Vernou 为此,我应该为所有线程只使用一个 dbContext,并且应该使用这个 dbContext 锁定每个方法。我说的对吗?
  • "对所有线程只使用一个 dbContext,并且应该使用这个 dbContext 锁定每个方法" 不。这不是一个好主意。上下文是一个轻量级缓存,并非设计为长期存在的。它的目的是使用和处置,通常通过using 声明......即在尽可能短的范围内。要处理并发,您可以将您的应用程序限制为一个编写器,或者使用 EF 提供的并发工具......除非您的编写非常有争议,否则乐观并发通常就足够了。我的观点是限制应用比基于数据库的冲突解决更可取。

标签: c# multithreading entity-framework .net-core entity-framework-core


【解决方案1】:

答案很简单。您目前无法使用 EF Core 实现完整的事务/锁定安全性。要正确地做事,您必须依赖您的数据库引擎机制。

你有两种方法来解决这个问题:

  • 直接访问 SQL,
  • 使用允许此类操作的 linq2db。

linq2db 可以流畅地与 EF Core 集成,并允许您正确处理 LOCK / 隔离级别等。

https://github.com/linq2db/linq2db.EntityFrameworkCore

【讨论】:

    猜你喜欢
    • 2019-02-23
    • 2016-08-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多