I think I may be missing something in my understanding of how this is supposed to work. I have some code that imports a file. It loops through each record, does some processing, then adds that record to a table via a DbContext
instance.
I initialize DbContext
like this:
protected void ResetDbContext()
{
if (_db != null)
_db.Dispose();
_db = new AppDBEntities();
_db.Configuration.AutoDetectChangesEnabled = false;
_db.Configuration.ValidateOnSaveEnabled = false;
}
My main loop looks something like this:
foreach (var rec in engine)
{
var record = new CommonImportRecord(rec);
ProcessRecord(record, options, index);
index++;
}
_db.SaveChanges();
ProcessRecord
looks something like this:
protected async Task<int> ProcessRecord(CommonImportRecord record, ImportOptions options, int index)
{
DisplayProcessStatus(index, options);
// Code removed which fills in various properties of the record
_db.MyTable.Add(record);
if (index % options.UpdateInterval == 0)
{
return await _db.SaveChangesAsync();
// This was originally here, commented out when I changed SaveChanges() to SaveChangesAsync()
// ResetDBContext();
}
}
The only real changes I made for SaveChangesAsync()
was to add async Task<int>
as the return type of ProcessRecord
, changed SaveChanges()
to return await SaveChangesAsync()
and commented out the call to ResetDBContext.
Things worked as expected before the async changes. Afterwards, it doesn't appear that all of my records are being saved.
What am I missing here?
You are calling an async
method which returns a task without waiting for it to complete. You need to use await
to asynchronously wait before moving on to the next record. It's also a standard to name your async
methods with the "Async" suffix:
foreach (var rec in engine)
{
var record = new CommonImportRecord(rec);
var result = await ProcessRecordAsync(record, options, index);
index++;
}
To add to @l3arnon's answer, you can save yourself the generating of a state machine inside ProcessRecordAsync
:
This:
protected async Task<int> ProcessRecordAsync(CommonImportRecord record, ImportOptions options, int index)
{
// Removed code for brevity
return await _db.SaveChangesAsync();
}
Can be turned into:
protected Task<int> ProcessRecordAsync(CommonImportRecord record, ImportOptions options, int index)
{
// Removed code for brevity
return _db.SaveChangesAsync();
}
As you're not really using the return value of SaveChangesAsync
inside the call to ProcessRecordAsync
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With