mehdime / DbContextScope

A simple and flexible way to manage your Entity Framework DbContext instances
http://mehdi.me/ambient-dbcontext-in-ef6/
MIT License
634 stars 271 forks source link

Recreating DbContext for better performance #20

Open emumanu opened 9 years ago

emumanu commented 9 years ago

Hello,

thank you very much for the DbContextScope!. I was looking for something like this to properly handling my DbContexts.

The only thing I'm missing at the moment is the ability to recreate a particular DbContext, because when I'm making a lot of inserts, the change tracker has to keep track of a lot of entities and I get better performance recreating the context.

So, I have added this functionality in the DbContextCollection class (and in the IDbContextCollection interface):

   public TDbContext GetNew<TDbContext>() where TDbContext : DbContext
    {
        var requestedType = typeof(TDbContext);

        // if the this context type wasn't created, create it using the Get method
        if (!_initializedDbContexts.ContainsKey(requestedType)) {
            return Get<TDbContext>();
        } else {
            // otherwise, we have to dispose and recreate this context type
            var dbContext = _initializedDbContexts[requestedType] as TDbContext;
            try {
                dbContext.Dispose();
            } catch (Exception e) {
                System.Diagnostics.Debug.WriteLine(e);
            }
            _initializedDbContexts.Remove(requestedType);

            return Get<TDbContext>();
        }
    }

I hope you find it useful and include it in your code.

mehdime commented 9 years ago

Thanks for the suggestion and sample code!

Would you be able to give a little bit more details of the situation in which this would be required? If I knew more about the context, I might be able to suggest alternatives to manually re-creating the DbContext.

emumanu commented 9 years ago

I'm importing a feed with 800000 products, generating a lot of updates and some inserts. Even I use AutoDetectChangesEnabled wisely to avoid calling DetectChanges several times, the memory consumption is too high (and double because I'm using a snapshot to detect changes), so I decided to split the task in several batches.

jbkielis commented 9 years ago

I also need something like this behavior. I'm updating ~500K records and I need to break it down into batches. Currently, if I call SaveChanges periodically (e.g., every 1000 records) I get the "cannot call SaveChanges more than once" error. Currently, what is the best way to handle this? Use ForceCreateNew? Thanks.