Foreach循环中的异步/等待(即循环ef模型)生成错误

cho*_*bo2 -2 c# async-await entity-framework-core asp.net-core

我有一个foreach循环,它第一次在它工作的第一个项目中找到但是当它到达下一个项目时,我得到了这个错误.

System.InvalidOperationException
  HResult=0x80131509
  Message=Error generated for warning 'Microsoft.EntityFrameworkCore.Infrastructure.LazyLoadOnDisposedContextWarning: An attempt was made to lazy-load navigation property 'Company' on entity type 'RecurringInvoiceTemplateProxy' after the associated DbContext was disposed.'. This exception can be suppressed or logged by passing event ID 'CoreEventId.LazyLoadOnDisposedContextWarning' to the 'ConfigureWarnings' method in 'DbContext.OnConfiguring' or 'AddDbContext'.
  Source=Microsoft.EntityFrameworkCore
  StackTrace:
   at Microsoft.EntityFrameworkCore.Diagnostics.EventDefinition`2.Log[TLoggerCategory](IDiagnosticsLogger`1 logger, WarningBehavior warningBehavior, TParam1 arg1, TParam2 arg2, Exception exception)
   at Microsoft.EntityFrameworkCore.Internal.CoreLoggerExtensions.LazyLoadOnDisposedContextWarning(IDiagnosticsLogger`1 diagnostics, DbContext context, Object entityType, String navigationName)
   at Microsoft.EntityFrameworkCore.Internal.LazyLoader.ShouldLoad(Object entity, String navigationName, NavigationEntry& navigationEntry)
   at Microsoft.EntityFrameworkCore.Internal.LazyLoader.Load(Object entity, String navigationName)
   at Microsoft.EntityFrameworkCore.Proxies.Internal.LazyLoadingInterceptor.Intercept(IInvocation invocation)
   at Castle.DynamicProxy.AbstractInvocation.Proceed()
   at Castle.Proxies.RecurringInvoiceTemplateProxy.get_Company()
   at SourceLine.Api.Services.InvoicingService.<>c__DisplayClass48_0.<GenerateRecurringInvoicesAsync>b__0(CustomerDto x) in 1299
   at System.Linq.Enumerable.TryGetFirst[TSource](IEnumerable`1 source, Func`2 predicate, Boolean& found)
   at System.Linq.Enumerable.FirstOrDefault[TSource](IEnumerable`1 source, Func`2 predicate)
   at SourceLine.Api.Services.InvoicingService.<GenerateRecurringInvoicesAsync>d__48.MoveNext() in line 1299
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Threading.ThreadPoolWorkQueue.Dispatch()
Run Code Online (Sandbox Code Playgroud)

我的查询

 return dbContext.RecurringInvoiceTemplates.Include(x => x.Company)
                                              .Include(x => x.RecurringInvoiceFrequency)
                                              .Where(x => x.NextRun.Date.CompareTo(currentTime.Date) <= 0).ToList();
Run Code Online (Sandbox Code Playgroud)

查询它死了

    foreach (var r in recurringInvoices){
     var foundCustomer = allCustomers.FirstOrDefault(x => x.Id == r.Company.Identifier);
}
Run Code Online (Sandbox Code Playgroud)

更新

问题可能实际上是因为这个原因

public async void Get(){

    var recurringInvoices = dbContext.RecurringInvoiceTemplates.Include(x => x.Company)
                                                  .Include(x => x.RecurringInvoiceFrequency)
                                                  .Where(x => 
    var allCustomer = new List<Dto>(){
        new Dto(){
            Id = 1
        }
    }

    foreach (var r in recurringInvoices)
    {
        //allcustomers is not en EF object, just a dto.
        var foundCustomer = allCustomers.FirstOrDefault(x => x.Id == r.Company.Identifier);

        if (foundCustomer != null)
        {

                var ApiKey = configuration["SendGrid:Key"];
                var sendGridClient = new SendGridClient(ApiKey);

                var msg = new SendGridMessage();
                msg.SetFrom(new EmailAddress("example@test.com, "Example User"));


                msg.SetTemplateId("d-f06bfad7374b4a3cb2ccbf846d8e96a4");


                var dynamicTemplateData = new SendInvoiceTemplateDto
                {
                    Subject = "a",
                    Body = "b"
                };

                msg.SetTemplateData(dynamicTemplateData);

                var response = await sendGridClient.SendEmailAsync(msg);
            }
        }
}
Run Code Online (Sandbox Code Playgroud)

所以似乎因为我使用异步它处理我的dbContext?

编辑2

我不明白,但是当我使用时

 var response = sendGridClient.SendEmailAsync(msg);
response.Wait();
Run Code Online (Sandbox Code Playgroud)

我不再遇到这个问题了.

Ste*_*ary 6

所以似乎因为我使用异步它处理我的dbContext?

你的问题是由于async void.你应该避免async void.引起的问题之一async void是该方法的调用者无法知道它何时完成.因此,调用者只是继续执行,最终完成HTTP请求并拆除控制器(以及任何依赖注入的控制器),处理DbContext并导致该异常,因为您的代码仍在运行.

解决的办法是改变async voidasync Task并有来电awaitTask从返回Get.如果Get是控制器动作,那么你只需要更改async voidasync Task; ASP.NET将自动Task正确处理.