C# 具有实体框架和并发性的Azure函数
我有一个IotHub触发器,它基本上使用实体框架将传入的id保存到数据库中,如果这样的id不存在的话C# 具有实体框架和并发性的Azure函数,c#,entity-framework,azure,azure-functions,azure-iot-hub,C#,Entity Framework,Azure,Azure Functions,Azure Iot Hub,我有一个IotHub触发器,它基本上使用实体框架将传入的id保存到数据库中,如果这样的id不存在的话 [FunctionName("MainFunc")] public static async Task Run( [IoTHubTrigger("messages/events", Connection = "IotHubCompatibleEndpointConnectionString", ConsumerG
[FunctionName("MainFunc")]
public static async Task Run(
[IoTHubTrigger("messages/events",
Connection = "IotHubCompatibleEndpointConnectionString",
ConsumerGroup = "ttx_iothub_trigger_sqldb_cg")]
EventData eventData, ILogger log)
{
string id = GetIdFromMessage(eventData);
var context = new MyEfDbContext();
InsertIfNotExists(id);
DoSomethingElse(context);
context.SaveChanges();
}
问题是,当有大量消息发送到iot集线器时,多个触发器调用开始并行工作(至少在我调试触发器时),这导致InsertIfNotExists()
方法出现问题,当数据库中不存在多个具有相同id的记录时,会导致重复密钥异常,正在处理中
最合适的修复方法是什么?只需吞下异常,因为该记录仍将出现在数据库中?您没有提供太多代码在InsertIfNotExists中执行的操作,但我认为您的问题是您有上下文。SaveChanges();最后,这意味着首先在内存中修改,然后保存,这意味着同时可以有多个实例执行相同的操作。这里最重要的是快速插入数据库,但即使这样也不能保证一次插入一个 所以我看这里没有什么选择 备选案文1。您还可以使用try-catch,在出现错误时,只需执行第二次trip以获取id,因为您知道已插入该记录 备选案文2。Transact-sql具有实际执行upsert的merge语句。如果您使用的是实体框架核心(您没有提供是否为其核心,但我假设为其核心),那么您可以使用 备选案文3。将是使用事务
DataContext.DailyVisits
.Upsert(new DailyVisit
{
UserID = userID,
Date = DateTime.UtcNow.Date,
Visits = 1,
})
.On(v => new { v.UserID, v.Date })
.WhenMatched(v => new DailyVisit
{
Visits = v.Visits + 1,
})
.RunAsync();