Entity Framework 6.2 very slow first startup and E

2019-07-23 19:17发布

this topic is already widely discussed on stackoverflow and many other blogs, reason to asking question is that i observe this topic was discussed in mostly 3 to 5 years old posts whereas we have EF 6.2 version now, and i expect this may have updates already (there are more reasons you will find in question.

My application has at least 25 Models(Tables) with MySQL as database, models and relations are configured in OnModelCreating, web site is hosted on godaddy and i do not have good access to IIS configurations etc.

Page load time

  • First page load: 65 to 70 seconds
  • 2nd page load: 1 to 3 seconds

After 10 minutes delay again it will takes 70 seconds to load page. Please note that i tested it in different environments, like using different internet connection. There are no pictures on the page, and test page has only 5 rows of data with two columns (calling simple method db.Test.ToList();)

While searching internet i found that is common problem with EF so i tried fixing it, while taking help from posts 3 Steps for Fast EntityFramework and Pregenerate Model and View Cache

After this fix

  • First page load: 64 to 67 seconds
  • 2nd page load: 1 to 3 seconds

    // DbConfiguration constructor
    public MyDbConfiguration
    {
         var path = Path.GetDirectoryName(this.GetType().Assembly.Location);
         SetModelStore(new DefaultDbModelStore(path));
    }
    
    // DbContext
    private static DbMappingViewCacheFactory viewCacheFactory;
    
    private static DbMappingViewCacheFactory ViewCacheFactory
    {
        get
        {
            if (viewCacheFactory == null)
            {
                var path =ConfigurationManager.AppSettings[GlobalContextConfig.EFCacheFolder];
                viewCacheFactory=new FileViewCacheFactory(path+"Budget.Context.MyDbContext.xml");
            }
            return viewCacheFactory;
        }
    }
    
    
    public MyDbContext()
        : base("name=MySqlConnectionString")
    {
         // In case i need to update xml for now i delete the old file manually 
        InteractiveViews.SetViewCacheFactory(this, ViewCacheFactory);
    
        Database.SetInitializer<MyDbContext>(null);
    
        this.Configuration.ProxyCreationEnabled = false;
        this.Configuration.LazyLoadingEnabled = false;
        this.Configuration.AutoDetectChangesEnabled = false;
        this.Configuration.ValidateOnSaveEnabled = false;
    }
    

It was improved but not enough, I want to know if these issues are updated in EF 6.2.0 or method of fixing it has changed, or any thing im doing wrong/should check.

I also installed EF 6.1.X and generated views by right clicking Contaxt file and choosing Entity Framework > Generate View in the manu

Results:

  • First page load: 40 to 50 seconds
  • 2nd page load: 0 to 1.5 seconds

That's quite amazing, EF 6.1.X is much faster than EF 6.2

Build and deployed as Release package with debug=false

For test purpose i also uploaded asp.net application without Entity Framework, it takes 8 to 13 seconds to load for first time, and second load takes in less than 1 seconds

2条回答
戒情不戒烟
2楼-- · 2019-07-23 19:58

I want to know if these issues are updated in EF 6.2.0 or method of fixing it has changed, or any thing im doing wrong/should check.

The answer is yes,

EF 6.2 has introduced a Model Cache

public class MyDbConfiguration : DbConfiguration
{
    public MyDbConfiguration() : base()
    {
        var path = Path.GetDirectoryName(this.GetType().Assembly.Location);
        SetModelStore(new DefaultDbModelStore(path));
    }
}

[DbConfigurationType(typeof(MyDbConfiguration))]
public class MyContextContext : DbContext 
{
}

You can learn more here: https://codeopinion.com/entity-framework-code-first-model-cache/

查看更多
The star\"
3楼-- · 2019-07-23 19:58

I assume you read the performance considerations:

https://docs.microsoft.com/en-us/dotnet/framework/data/adonet/ef/performance-considerations

I am personally struggling with these issues aswell. I resorted to a) creating custom SQL for some queries. and b) I created a warmup mechanism. There is also an option to precompile queries which might help.

The warmup mechanism runs at the start of the application on a seperate thread. There it does a very simple request to the database, this forces the creation of the model, and 'triggers' the initial startup delay for all queries. After that query has ran (it takes a couple seconds) a flag gets set. All other operations wait for the flag being set before running. Especially in a multithreaded scenario this helps a lot.

I found out that the startup delay was created per thread. This means that if the delay is let's say 2 seconds, running 3 threads who all create a context and try to run some linq, make the whole application wait for 6 seconds.

Note that by creating custom queries, one must return all fields for the entity to be created;

    var blogs = context.Blogs.SqlQuery("SELECT * FROM dbo.Blogs").ToList(); //works
    var blogs = context.Blogs.SqlQuery("SELECT [id] FROM dbo.Blogs").ToList(); //Does not.

I have not tested this matter fully - so take some time to test. This is just a heads up.

查看更多
登录 后发表回答