【问题标题】:Async/Await in Foreach Loop(That is looping ef models) Generates an ErrorForeach 循环中的 Async/Await(即循环 ef 模型)生成错误
【发布时间】:2019-03-01 08:52:40
【问题描述】:

我有一个 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()

我的查询

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

查询它死了

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

更新

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

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);
            }
        }
}

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

编辑 2

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

 var response = sendGridClient.SendEmailAsync(msg);
response.Wait();

我不再遇到这个问题了。

【问题讨论】:

  • 当你使用 include:Include(x =&gt; x.Company) 那么公司没有延迟加载......所以不要认为这是问题......你需要看看公司在哪里被延迟加载,或者从您的实体中的公司中删除 virtual,以关闭延迟加载。
  • @HoomanBahreini - 这似乎与我在 foreach 中有 async/await 并导致问题的事实有关。
  • @chobo2 避免使用async void。将方法更改为返回 Task 并在堆栈中等待该方法。您可能没有等待该方法的调用,因此上下文在您完成之前已被处理。

标签: c# asp.net-core async-await entity-framework-core


【解决方案1】:

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

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

解决方案是将async void 更改为async Task 并让调用者awaitGet 返回Task。如果Get 是控制器动作,那么您只需将async void 更改为async Task; ASP.NET 会自动正确处理Task

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-06-23
    • 2020-05-30
    • 1970-01-01
    • 1970-01-01
    • 2016-12-30
    • 2019-07-16
    • 1970-01-01
    相关资源
    最近更新 更多