在Azure QueueTrigger函数(多线程)中发布插入/更新EF Core DbContext

时间:2018-10-16 07:57:19

标签: entity-framework-core azure-functions entity-framework-core-2.1

Azure QueueTrigger函数中使用 EF Core 2.1 DbContext 时,我遇到PK违反异常。猜猜是由于DbContext的本质不是线程安全,并且Azure Function并行运行不同的实例。我已经读了很多书,但是我找不到解决这个问题的好方法。

这是我的情况(生产者-消费者模式):

我有一个预定的Azure函数,该函数正在调用API从不同的外部系统获取项目。为了获得项目的所有必需信息,我需要对其他外部服务运行不同的查询,因此我将其与另一个Azure函数解耦,因此Scheduled函数仅将每个项目的消息排队,如“ 同步项目” ID 101 ”。

每次邮件排队时都会触发另一个 QueueTrigger函数,因此,这意味着并行运行的不同实例。此功能必须收集特定 Project 的所有数据,这意味着需要更多调用其他外部服务/ API,以(某种形式)汇总有关 Project 的所有信息。 >。恕我直言,这样做是一件好事,因为我可以并行处理多个项目,并且可以根据需要扩展功能。

一旦有了所有这些 Project 信息,我想使用EF Core将其保存在SQL DB中(这是问题所在)

项目数据包括项目中的用户,并且每个用户都有特定的 GUID 作为PK(来自外部系统)。这意味着我可以在不同的Function实例中重复使用用户ID,这就是问题所在,因为当我尝试将用户信息保留在SQL表中时,由于多个Function实例可以尝试插入同一用户,因此我会收到PK Duplicate异常。同时(实例A检查用户是否存在时,它为False,而另一个实例B实际上正在添加该用户,因此,当实例A尝试插入时,它将失败)。

猜猜我可以以某种方式锁定DbContext,但不确定是否很好,因为我还有一个网站正在对SQL DB进行查询(目前为只读查询,但将来也可能会进行更新)。

另一个想法是将整个项目信息发送到另一个Queue / Blob文件,并在 Singleton 模式下具有另一个功能,该功能可将数据插入SQL。

我创建了这个项目,简化了我的场景,但是足以重现问题并理解问题。 https://github.com/luismanez/queuetrigger-efcore-multithreading

还有其他想法或推荐的方法吗? (如果发现更好的内容,可以更改架构)

非常感谢!

1 个答案:

答案 0 :(得分:0)

“更简单”的方法可能是在数据库中进行某种更新。以下是使用EF Core如何做到这一点的示例:https://www.flexlabs.org/2018/02/adding-upsert-support-for-entity-framework-core