1 year ago

#71957

test-img

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

Accepted video resources