Ho un ciclo foreach e la prima volta che gira nel primo elemento funziona, ma quando arriva al prossimo elemento, ottengo questo errore.
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()
la mia domanda
return dbContext.RecurringInvoiceTemplates.Include(x => x.Company)
.Include(x => x.RecurringInvoiceFrequency)
.Where(x => x.NextRun.Date.CompareTo(currentTime.Date) <= 0).ToList();
Interrogarsi muore
foreach (var r in recurringInvoices){
var foundCustomer = allCustomers.FirstOrDefault(x => x.Id == r.Company.Identifier);
}
Aggiornare
Il problema potrebbe essere in realtà è a causa di questo
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);
}
}
}
Quindi sembra che dal momento che sto usando async disponga il mio dbContext?
Modifica 2
Non capisco ma quando lo uso
var response = sendGridClient.SendEmailAsync(msg);
response.Wait();
Non ho più questo problema.
Quindi sembra che dal momento che sto usando async disponga il mio dbContext?
Il tuo problema è dovuto al async void
. Dovresti evitare il async void
. Uno dei problemi causati dal async void
è che il chiamante di quel metodo non può sapere quando è stato completato. Quindi, il chiamante continua a eseguire, alla fine completando la richiesta HTTP e abbattendo il controller (e qualsiasi cosa in cui è stata inserita la dipendenza), DbContext
e causando DbContext
perché il codice è ancora in esecuzione .
La soluzione è di cambiare il async void
async Task
e fare in modo che il chiamante await
l' Task
restituita da Get
. Se Get
è un'azione del controllore, devi solo cambiare il async void
async Task
; ASP.NET gestirà automaticamente l' Task
correttamente.