In my application it is sometimes necessary to save 10,000 or more rows to the database in one operation. I've found that simply iterating and adding each item one at a time can take upwards of half an hour.
However, if I disable AutoDetectChangesEnabled it takes ~ 5 seconds (which is exactly what I want)
I'm trying to make an extension method called "AddRange" to DbSet which will disable AutoDetectChangesEnabled and then re-enable it upon completion.
public static void AddRange<TEntity>(this DbSet<TEntity> set, DbContext con, IEnumerable<TEntity> items) where TEntity : class
{
// Disable auto detect changes for speed
var detectChanges = con.Configuration.AutoDetectChangesEnabled;
try
{
con.Configuration.AutoDetectChangesEnabled = false;
foreach (var item in items)
{
set.Add(item);
}
}
finally
{
con.Configuration.AutoDetectChangesEnabled = detectChanges;
}
}
So, my question is: Is there a way to get the DbContext from a DbSet? I don't like making it a parameter - It feels like it should be unnecessary.
Why are you doing this on the DbSet? Try doing it on the DbContext instead:
Then using it is as simple as:
maybe you could create a helper that disabled this for you and then just call the helper from within the AddRange method
With Entity Framework Core (tested with Version 2.1) you can get the current context using
How to get a DbContext from a DbSet in EntityFramework Core 2.0
Yes, you can get the
DbContext
from aDbSet<TEntity>
, but the solution is reflection heavy. I have provided an example of how to do this below.I tested the following code and it was able to successfully retrieve the
DbContext
instance from which theDbSet
was generated. Please note that, although it does answer your question, there is almost certainly a better solution to your problem.Example usage:
Explanation:
According to Reflector,
DbSet<TEntity>
has a private field_internalSet
of typeInternalSet<TEntity>
. The type is internal to the EntityFramework dll. It inherits fromInternalQuery<TElement>
(whereTEntity : TElement
).InternalQuery<TElement>
is also internal to the EntityFramework dll. It has a private field_internalContext
of typeInternalContext
.InternalContext
is also internal to EntityFramework. However,InternalContext
exposes a publicDbContext
property calledOwner
. So, if you have aDbSet<TEntity>
, you can get a reference to theDbContext
owner, by accessing each of those properties reflectively and casting the final result toDbContext
.Update from @LoneyPixel
In EF7 there is a private field _context directly in the class the implements DbSet. It's not hard to expose this field publicly