EF 核心错误与交易但不使用交易

EF core error with transaction but not using trasactions

最近我们的一位测试员报告了我们应用程序的错误。 此错误似乎与 EF 核心事务有关,但我们没有在代码中使用事务。但是我们在这个应用上根本没有使用交易。

当多个用户连接到我们的应用程序时,这个问题似乎是随机发生的。

错误是:

Error : System.invalidOperationException
BeginExecuteReader require the command to have a transaction when the connection assigned to the command is in a pending local transaction. 
The transaction property of the command has not been initialized.

从堆栈跟踪来看,当我们在名为“SurveyOperations”的 class 中执行以下操作时,就会发生此错误:

Survey surveyToSave = await _context.Surveys.FindAsync(id);

详情:

_context 在 SurveyOperations 构造函数中使用 asp.net 核心依赖注入进行初始化。

在 startup.cs 中,SurveyOperations 的范围为“瞬态”,数据库连接也是如此。 我们 100% 的 EF 核心调用都是异步的。

我们在使用 OwningComponentBase 注入 SurveyOperations 的 Blazor 组件上遇到此错误:

@using Microsoft.Extensions.DependencyInjection
@inherits OwningComponentBase

@code{
   private SurveyOperations _surveyOperations;
   private Survey survey;

   protected override async Task OnInitializedAsync()
   {
       _surveyOperations = ScopedServices.GetRequiredService<SurveyOperations>();
      survey = await _surveyOperations.GetSurveyAsync(id);
   }

   private async Task HandleValidSubmit()
   {
      // Get sone data from the form on the component

      await _surveyOperations.SaveSurvey(survey);

   }
}
```

We suspect that EF core is reusing connections but we didn't know how to avoid that.

在我看来,您的设计是错误的,使用 OwningComponentBase 并不能确保您免受在 Blazor 中使用 DbContext 引起的问题。您可以使用以下方法之一解决此问题:

@inherits OwningComponentBase<AppDbContext>

AppDbContext 是您的 DbContext

或者更好,更适合您的设计,实施 IDbContextFactory...在这种情况下,您可以像这样配置 dbcontext:

builder.Services.AddDbContextFactory<ContactContext>(opt =>
    opt.UseSqlite($"Data Source={nameof(ContactContext.ContactsDb)}.db"))

在这里查看完整的解释:full explanation

在您的 SurveyOperations 服务中,您可以这样做:

public SurveyOperations(IDbContextFactory<ContactContext> factory)
{
    DbFactory = factory;
}

在你的各种方法中你可以做这样的事情:

using var _context = DbFactory.CreateDbContext();    

Survey surveyToSave = await _context.Surveys.FindAsync(id);

请注意,第二个选项使 OwningComponentBase 的使用变得多余。