首页 > 解决方案 > SaveChangesAsync 到数据库上下文是否在 .net 5 隔离的 azure 函数应用程序中的 while 循环内正常

问题描述

我有一个 .net 5 函数应用程序,它需要运行一堆协议,检查它们是否已经被函数应用程序的另一个实例处理,如果没有,则通过将 id 添加到 AgreementProcessing 表并根据需要进行更新来锁定它. 我正在使用 LINQ。

我总是尝试在 for 循环之后保存到数据库,但在这种情况下,我需要循环并等待对协议的更改一段时间,并且由于在任何给定时间可能有多个实例运行,我还需要锁定那些我要处理的协议。

这基本上看起来像这样:

while (true)
{
  var dbAgreements = _context.Agreements.Where(a => a.Processed == false && 
                                   a.Status == "PENDING" &&
                                   a.Created.AddMinutes(5) < DateTime.Now &&
                                   !_context.AgreementProcessing.Any(p => p.AgreementId == 
                                   a.AgreementId)).ToList();

  if (dbAgreements == null && dbAgreements.Count == 0)
  {
    return false;
  }

  if (dbAgreementsToProcess != null && dbAgreementsToProcess.Count > 0)
  {
    var dbAgreementsToProcess = await SetAgreementsToProcessing(dbAgreements);      

    foreach (var dbAgreement in dbAgreementsToProcess)
    {
       await ProcessAgreement(dbAgreement);
    }

    await _context.SaveChangesAsync();

    // wait one second and check again
    await Task.Delay(1000);
  }
}

SetAgreementsToProcessing的简化版本如下所示:

private async Task<List<Agreement>> SetAgreementsToProcessing(List<Agreement> dbAgreements)
{
  List<Agreement> result = null;
  List<Agreement> agreementsToProcess = new List<Agreement>();

  foreach (var dbAgreement in dbAgreements)
  {
    if (CheckIfStatusChanged(dbAgreement)
    {
      AgreementProcessing processing = new AgreementProcessing() { id = dbAgreement.Id};
    }

    _context.AgreementProcessing.Add(processing);

    agreementsToProcess.Add(dbAgreement);
  }

  try
  {
    int dbUpdates = await _context.SaveChangesAsync();

    if (dbUpdates > 0)
    {
       // only if we get here are there items to be processed
       result = agreementsToProcess;
    }
  }
  catch (Exception ex)
  {
      // logs error
  }

  return result;
}

所以我在 while 循环中调用了 SaveChangesAsync 两次。一次是在 SetAgreementsToProcessing 中,第二次是在处理完所有协议之后(如果没有处理任何协议,则不会执行任何操作)。

我对这个解决方案感到不安,因为我通常会在循环中避免 SaveChangesAsync。我正在考虑是否应该摆脱 while 循环,相反,如果我走到最后,只需安排函数应用程序的一个新实例来处理。我可能会这样做,但欢迎提出其他建议(或警告)。

标签: c#.netlinqazure-functions

解决方案


推荐阅读