【发布时间】:2018-10-16 07:57:19
【问题描述】:
在 Azure QueueTrigger 函数中使用 EF Core 2.1 DbContext 时出现 PK 违规异常。猜测是由于 DbContext 的性质不是线程安全,并且 Azure 函数并行运行不同的实例。我已经阅读了很多,但我找不到解决这个问题的好方法。
这是我的场景(生产者-消费者模式):
我有一个 Scheduled Azure Function,它正在调用 API 以从不同的外部系统获取项目。要获取项目所需的所有信息,我需要对其他外部服务运行不同的查询,因此我将其与另一个 Azure 函数解耦,因此计划函数只是将每个项目的消息排队,如“同步项目” ID 101”。
另一个QueueTrigger函数在每次消息排队时触发,因此,这意味着不同的实例并行运行。此函数必须收集特定 Project 的所有数据,这意味着对其他外部服务/API 的更多调用,以(某种)聚合有关 Project 的所有信息>。恕我直言,这样做很好,因为我可以并行处理多个项目,并且可以根据需要扩展功能。
获得所有这些项目信息后,我想使用 EF Core 将其保存在 SQL DB 中(问题来了)
项目数据包括项目中的用户,每个用户都有一个特定的 GUID 作为 PK(来自外部系统)。这意味着我可以在不同的函数实例中重复用户 ID,这就是问题所在,因为当我尝试将用户信息保留在 SQL 表中时,我可以得到 PK 重复异常,因为多个函数实例可以尝试插入同一个用户同时(当实例A检查用户是否存在时,它得到了False,但另一个实例B实际上正在添加这个用户,所以当实例A尝试插入时,它失败了)。
我想我可以以某种方式锁定 DbContext,但不确定是否好用,因为我还有一个网站对 SQL DB 进行查询(目前是只读查询,但将来也可能会更新)。
另一个想法可能是将整个项目信息发送到另一个队列 / Blob 文件,并在 单例 模式下具有另一个功能,将数据插入 SQL。
我创建了这个项目来简化我的场景,但足以重现问题并理解问题。 https://github.com/luismanez/queuetrigger-efcore-multithreading
还有其他想法或推荐的方法吗? (如果发现更好的东西,可以改变架构)
非常感谢!
【问题讨论】:
-
持久功能模式#2:扇出/扇入似乎是一个很好的选择:docs.microsoft.com/en-us/azure/azure-functions/…
标签: entity-framework-core azure-functions entity-framework-core-2.1