1 year ago
#71957
nickfinity
Can I run code in parallel that is using Entity Framework to insert data?
I've seen a lot of posts about this, but I'm still not quite sure what the answer is. I inherited some code that is handling items one by one. It does a bunch of stuff (it's somewhat CPU intensive), then needs to save data to the database, and update the status of the item. It uses EF.
Here is the existing method:
private void CheckForThingsToDo(IContainer container)
{
var finished = false;
while (!finished)
{
using (var scope = container.BeginLifetimeScope("Console Request"))
{
var queries = scope.Resolve<IQueries>();
var commands = scope.Resolve<ICommands>();
var context = scope.Resolve<IContext>();
var nextItem = queries.GetNextItem();
finished = (nextItem == null);
if (finished) continue;
using (var transaction = context.BeginTransaction())
{
if (nextItem == null) return;
try
{
commands.ProcessItem(nextItem.Id); // this is somewhat CPU intensive
transaction.Commit();
}
catch(Exception ex)
{
_logger.Error(ex.Message, ex);
}
}
}
}
}
I would like to be able to run these in parallel because it's maxing out one core and the rest of the server is sitting there.
private void CheckForThingsToDoParallel(IContainer container)
{
using (var scope = container.BeginLifetimeScope("Console Request"))
{
var context0 = new EntityFrameworkRecordkeepingContext();
var queries = new AccountTransactionQueries(context0, mapper);
var items = queries.GetItems();
Parallel.ForEach(items,
new ParallelOptions { MaxDegreeOfParallelism = 4 },
() => new EntityFrameworkRecordkeepingContext(),
(item, parallelLoopState, context) =>
{
try
{
var queries = new Queries(context);
var repo = new Repository(context);
var commands = new Commands(repo, queries);
using (var transaction = context.BeginTransaction())
{
commands.ProcessItem(nextBatchItem);
transaction.Commit();
}
}
catch (Exception ex)
{
_logger.Error(ex.Message, ex);
}
return context;
},
(context) =>
{
context.Dispose();
});
}
}
Should something like that work? It works some of the time. But I end up getting this error:
DbUpdateConcurrencyException: Store update, insert, or delete statement affected an unexpected number of rows (0). Entities may have been modified or deleted since entities were loaded
Each item is a separate thing, so any inserts done in relation to one item should not impact another set of inserts from a different item.
I feel like I might be missing something obvious. Some of the parallel code is me trying to figure stuff out. Any thoughts? I need a push in the right direction.
c#
entity-framework
entity-framework-6
task-parallel-library
0 Answers
Your Answer