I have a foreach loop and the first time it goes around in the first item it works find but when it gets to the next item, I get this error.
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()
my query
return dbContext.RecurringInvoiceTemplates.Include(x => x.Company)
.Include(x => x.RecurringInvoiceFrequency)
.Where(x => x.NextRun.Date.CompareTo(currentTime.Date) <= 0).ToList();
Query it dies on
foreach (var r in recurringInvoices){
var foundCustomer = allCustomers.FirstOrDefault(x => x.Id == r.Company.Identifier);
}
Update
The problem might be actually is because of this
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);
}
}
}
So it seems like since I am using async it disposes my dbContext?
Edit 2
I don't understand but when I use
var response = sendGridClient.SendEmailAsync(msg);
response.Wait();
I don't get this problem anymore.
So it seems like since I am using async it disposes my dbContext?
Your problem is due to async void
. You should avoid async void
. One of the problems caused by async void
is that the caller of that method cannot know when it has completed. So, the caller just keeps on executing, eventually completing the HTTP request and tearing down the controller (and anything you have dependency-injected into it), disposing the DbContext
and causing that exception because your code is still running.
The solution is to change the async void
to async Task
and have the caller await
the Task
returned from Get
. If Get
is a controller action, then you just have to change the async void
to async Task
; ASP.NET will automatically handle the Task
correctly.
User contributions licensed under CC BY-SA 3.0