C# Foreach循环(即循环ef模型)中的Async/Await生成错误
我有一个foreach循环,当它第一次在第一个项目中运行时,它可以找到,但是当它到达下一个项目时,我得到了这个错误C# Foreach循环(即循环ef模型)中的Async/Await生成错误,c#,asp.net-core,async-await,entity-framework-core,C#,Asp.net Core,Async Await,Entity Framework Core,我有一个foreach循环,当它第一次在第一个项目中运行时,它可以找到,但是当它到达下一个项目时,我得到了这个错误 System.InvalidOperationException HResult=0x80131509 Message=Error generated for warning 'Microsoft.EntityFrameworkCore.Infrastructure.LazyLoadOnDisposedContextWarning: An attempt was made
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()
更新
问题可能就是因为这个
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了
您的问题是由于async void
引起的。你应该。async void
引起的一个问题是,该方法的调用方无法知道它何时完成。因此,调用者只是继续执行,最终完成HTTP请求并拆下控制器(以及注入依赖项的任何东西),处理DbContext
,并导致异常,因为代码仍在运行
解决方案是将
async void
更改为async Task
,并让调用者等待从Get
返回的Task
。如果Get
是一个控制器操作,那么您只需将async void
更改为async Task
;ASP.NET将自动正确处理任务。当您使用include:include(x=>x.Company)
时,公司不会延迟加载。。。所以不要认为这是问题所在。。。您需要查看公司被延迟加载的位置,或者从实体中的公司中删除virtual
,以关闭延迟加载。@HoomanBahreini-我在foreach中有async/wait,这可能会导致问题。@chobo2避免使用async void
。将方法更改为返回Task
,并在堆栈中等待该方法。很可能您没有等待该方法的调用,因此在使用该方法之前,上下文已被处理。
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);
}
}
}
var response = sendGridClient.SendEmailAsync(msg);
response.Wait();