实体框架并发和Azure功能

时间:2018-02-27 06:18:33

标签: c# entity-framework azure azure-sql-database azure-functions

这个问题可能不仅仅特定于Azure功能,但对我来说就是这个场景。我有azure函数,它处理来自服务总线主题订阅的消息。消息用于在sql azure服务器上的表中添加/更新数据。

对于数据库操作,我使用的是Entity framework 6.2

我的消息可以是100个,但可能只有第一条消息是应该在数据库中插入条目的消息,接下来的几条消息是同一条记录的更新。

现在,在我的Azure函数中,我的host.json看起来像这样。

{
 "serviceBus": {
 "maxConcurrentCalls": 16,
 "prefetchCount": 20,
 "autoRenewTimeout": "00:05:00"
}
}

这意味着,它应该能够同时处理16条消息,它就是这样做的。

然而,对于并发处理,实体框架上下文不会从并行运行事务更新,我最终有10行,我应该在数据库中只有1行,因为它基本上是相同的记录。

是否有针对此的实体框架特定解决方案?

1 个答案:

答案 0 :(得分:1)

您要做的是将属于同一实体的邮件的处理限制为1。有几种方法可以做到这一点:

  1. 要在Entity Framework级别解决此问题,您需要使用Serializable隔离级别将读写操作正确地包装到单个事务中。然而,它并没有多大意义:您对消息进行并行处理,但在数据库级别上使用昂贵的锁来限制并行化。

  2. 使用数据库级约束(如唯一索引),然后确保每条消息都为同一实体插入具有相同唯一键的行。尝试编写它的第二个操作将获得约束违规异常,将重试将导致更新的操作。

  3. 只需将maxConcurrentCalls限制为1,并且永远不会运行多个函数实例。这是最简单的方法,但显然它不会为更高的负载进行扩展。

  4. 使用基于实体密钥的服务总线会话,即将相同实体的消息发送到同一会话。但坏消息:Azure Functions不支持Service Bus会话,因此您必须回退到手动处理。

  5. 使用例如事件中心而不是服务总线订阅。按实体ID对事件进行分区,然后按照In order event processing with Azure Functions

  6. 中的说明配置您的函数