【问题标题】:Entity Framework 6.2 very slow first startup and EFInteractiveViewsEntity Framework 6.2 首次启动和 EFInteractiveViews 非常慢
【发布时间】:2018-09-17 22:27:20
【问题描述】:

这个话题已经在 stackoverflow 和许多其他博客上广泛讨论,提出问题的原因是我观察到这个话题在大多数 3 到 5 年前的帖子中讨论过,而我们现在有 EF 6.2 版本,我希望这可能有已经更新(您会发现更多原因。

我的应用程序至少有 25 个模型(表),其中 MySQL 作为数据库,模型和关系在 OnModelCreating 中配置,网站托管在 godaddy 上,我无法很好地访问 IIS 配置等。

页面加载时间

  • 首页加载时间:65 到 70 秒
  • 第二页加载:1 到 3 秒

再次延迟 10 分钟后,加载页面需要 70 秒。 请注意,我在不同的环境中对其进行了测试,例如使用不同的互联网连接。 页面没有图片,测试页面只有5行2列数据(调用简单方法db.Test.ToList();)

在搜索互联网时,我发现这是 EF 的常见问题,所以我尝试修复它,同时从帖子 3 Steps for Fast EntityFrameworkPregenerate Model and View Cache 获得帮助

修复后

  • 首页加载时间:64 到 67 秒
  • 第二页加载:1 到 3 秒

    // 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;
    }
    

已经改进但还不够,我想知道这些问题是否在 EF 6.2.0 中更新或修复它的方法已更改,或者我做错了什么/应该检查。

我还安装了 EF 6.1.X 并通过右键单击 Contaxt 文件并在手册中选择 Entity Framework > Generate View 来生成视图

结果:

  • 首页加载时间:40 到 50 秒
  • 第二页加载:0 到 1.5 秒

太神奇了,EF 6.1.X 比 EF 6.2 快很多

使用 debug=false 构建和部署为 Release 包

出于测试目的,我还上传了没有实体框架的asp.net应用程序,第一次加载需要8到13秒,第二次加载不到1秒

【问题讨论】:

  • 你有没有解决这个问题?我有同样的问题,初始启动非常缓慢。
  • 如果你的网站是第三方网站,比如godaddy,那真的很难,我还在努力。如果您在本地托管,那么它不应该花费太长时间。将上下文划分为多个上下文,例如销售、客户等。禁用调试,不要使用延迟加载,关闭自动检测更改,有很多帖子描述不同的事情,

标签: asp.net-mvc entity-framework entity-framework-6 linq-to-entities


【解决方案1】:

我想知道这些问题是否在 EF 6.2.0 中更新或修复方法已更改,或者我做错了什么/应该检查。

答案是肯定的,

EF 6.2 引入了模型缓存

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 
{
}

您可以在这里了解更多信息:https://codeopinion.com/entity-framework-code-first-model-cache/

【讨论】:

  • 是的,我也做过这个配置,正如我提到的文章,
  • 是否有第三方工具来处理缓存或二级缓存
  • 答案取决于“处理缓存”的含义。缓存查询?缓存模型?
  • 关于缓存模型
  • 他们可能有,但我不知道
【解决方案2】:

我假设您阅读了性能注意事项:

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

我个人也在努力解决这些问题。我求助于a) creating custom SQL for some queries。 b)我创建了一个热身机制。还有一个预编译查询的选项可能会有所帮助。

预热机制在应用程序启动时在单独的线程上运行。在那里它向数据库发出一个非常简单的请求,这会强制创建模型,并“触发”所有查询的初始启动延迟。在该查询运行后(需要几秒钟)一个标志被设置。所有其他操作在运行之前等待标志被设置。尤其是在多线程场景中,这很有帮助。

我发现启动延迟是每个线程创建的。这意味着如果延迟是 2 秒,运行 3 个线程,它们都创建一个上下文并尝试运行一些 linq,让整个应用程序等待 6 秒

请注意,通过创建自定义查询,必须返回要创建的实体的所有字段;

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

我还没有完全测试这个问题 - 所以需要一些时间来测试。这只是一个提示。

【讨论】:

  • 感谢分享,我的场景变得更加复杂,因为我正在使用 godaddy 托管的网站,此时我没有足够的访问权限来访问 IIS 配置,ASP.Net 变成了垃圾,它慢得可怕。使用自定义查询对我来说没有意义,那我为什么要使用实体框架?我建立自己的数据访问框架会更好,这只需一次努力。我从我的经验中了解到,ASP.Net 只适合本地解决方案,其他领域可能不在他们的目标范围内。因为 EF Core 有同样的问题意味着他们不会修复它。
  • “我使用自定义查询没有意义,那我为什么要使用实体框架?”当然是为了速度!您正在消灭另一层,同时仍将有用的对象保留在代码中。它更多的是不需要在对象中编写验证和填充字段以及解析字符串之类的东西。
  • 我创建了一个预热机制——在 Application_Start 中,并将它放在一个由 Windows 服务定期调用的 ApiController 中。当我第一次执行查询时,它仍然很慢,但后续调用很快。在执行此操作之前运行预热机制没有任何区别。我没有像您一样使用 SqlQuery,而是在与我的表关联的 DbSet 上调用 .Any() 或 .FirstOrDefault() 。我在这里做错了什么?
  • 在多个线程中执行此操作可能会导致此行为。所以线程 A 开始查询,然后线程 B 开始另一个查询,而 A 尚未完全完成。这也可能取决于您的 EF 版本顺便说一句,这个线程是关于 EF6.2 - 较新的版本,尤其是 EF 核心可能有不同的行为。然后剩下的真的取决于你的实施,所以现在对我来说很难说。检查 sql 探查器是您的 .Any() 在数据库中实际触发 sql 吗?你的上下文模型是什么,你每次都创建一个新的吗?
猜你喜欢
  • 2019-02-24
  • 1970-01-01
  • 1970-01-01
  • 2012-11-29
  • 2016-07-18
  • 1970-01-01
  • 1970-01-01
  • 2018-03-22
  • 2015-04-04
相关资源
最近更新 更多