astef
astef

Reputation: 9508

EF6 Database First DbContext first query very slow

I've experimented with these methods of entity retrieval:

Generic, with Single: ~0.05s

var obj = MyDbContext.Set<Person>().Single(p => p.Id == 2);

Generic, with Find: ~4s

var obj = MyDbContext.Set<Person>().Find(2);

Non-generic, with Find: ~4s

var obj = (Person)MyDbContext.Set(typeof(Person)).Find(2);

And I can't figure out, why time is so differ?

I've read this old question: DbSet.Find method ridiculously slow compared to .SingleOrDefault on ID

And it is not my issue, because I have

MyDbContext.Configuration.AutoDetectChangesEnabled = false;

While it is the first query on MyDbContext instance, I'm doing a lot of work with another instances before these measurments and caching can be related somehow.

Second and next calls by all three methods are fast.

The problem is that I can't use generic method, because I receive the type of set at run-time.

Upvotes: 2

Views: 1074

Answers (2)

Rakoo
Rakoo

Reputation: 546

I had similar problem with EDMX model. The first query was very slow. I have resolved my problem by caching MetadataWorkspace while creating DbContext:

private static readonly Lazy<MetadataWorkspace> EntitiesMetadataWorkspace;

static MyWrapper()
{
    EntitiesMetadataWorkspace = new Lazy<MetadataWorkspace>(() => new MetadataWorkspace(CommonDbConfiguration.ModelMetadataArray, new[] { CommonDbConfiguration.ModelAssembly }), LazyThreadSafetyMode.ExecutionAndPublication);
}

public MyWrapper(OracleConnection oracleConnection)
{
    this.entities = new Lazy<Entities>(() => new Entities(new     EntityConnection(EntitiesMetadataWorkspace.Value, oracleConnection, false), false));
}

*Entities - my DbContext class.

Upvotes: 2

Omar.Alani
Omar.Alani

Reputation: 4130

Find vs Single cannot be the same, because Find checks the memory first for the required entity and if it wasn't tracked and exists in the memory the EF requests the entity from the database by generating the sql query like with single. Also you need to add the startup time for the context and that depends on how fat is your context also whether if this was the first call that will lead to create the database.

EDIT

I wanted to mention here also, that since EF6 is distributed by nuget (outside of .NET), the machine which runs on will use JIT compilation when your app is running so your processor can understand the code, .NET has a native image generating tool called "ngen", and what is does it let's you compile an assembly into a native image that uses code specific to your processor and stores it in a native image cache so your app uses that cache image instead of JITing it everytime you run your app.

So you can use ngen to speed up your startup through this command that you can run in VS 2012/2013 command line :

ngen install entityframework.dll

Hope this helps.

Upvotes: -1

Related Questions