EF6.2加载速度慢的解决方案

时间:2022-09-02 19:22:24

最近的项目中一直有反馈,EF在第一次启动之后调用的话,加载速度很慢,在网上搜索了一下,基本就是三种解决方案。

  1. 在程序启动的时候将映射视图缓存下来。
  2. 使用Ngen生成EF的本地镜像。
  3. IIS8内置功能 application Initialization,或者设置IIS的休眠时间(该条和EF已经没多大关系了)

三种办法的具体实施步骤,在网上都能搜索的到。

本次主要想描述一下第一种方法,在网上基本都是提供自己缓存映射视图的方法,总感觉不太好,提供的代码如下:

1 using (var dbcontext = new MyDbContext())
2 {
3     var objectContext = ((IObjectContextAdapter)dbcontext).ObjectContext;
4     var mappingCollection = (StorageMappingItemCollection)objectContext.MetadataWorkspace.GetItemCollection(DataSpace.CSSpace);
5     mappingCollection.GenerateViews(new List<EdmSchemaError>());
6 }

目的很明确,将DbContext中的视图读取并生成。其实在EF6.2发布的时候,已经解决了该类的问题。问题地址如下 https://github.com/aspnet/EntityFramework6/issues/275

方法很简单,使用代码配置,(官方说明:https://docs.microsoft.com/zh-cn/ef/ef6/fundamentals/configuring/code-based),新建MyDbConfiguration类,并且继承DbConfiguration。

1 public class MyDbConfiguration : DbConfiguration
2 {
3     public MyDbConfiguration() : base()
4     {
5         var path = Path.GetDirectoryName(this.GetType().Assembly.Location);
6         SetModelStore(new DefaultDbModelStore(path));
7     }
8 }

之后再使用的上下文类上打上属性[DbConfigurationType(typeof(MyDbConfiguration))]

1 [DbConfigurationType(typeof(MyDbConfiguration))]
2 public class MyContextContext : DbContext 
3 {
4 }

并且在项目启动的时候,需要手动初始化,即

1 using (var dbContext = new MyContextContext())
2      dbContext.Database.Initialize(true);

刚开始没有手动初始化,所以在启动的时候一直不生成edmx文件。之后再启动的时候,在C:\Windows\Microsoft.NET\Framework64\v4.0.30319\Temporary ASP.NET Files\openapi\caafd260\cddc743d\assembly\dl3路径下会生成随机的文件名,在该随机文件下,生成exmx文件。后续在启动的时候,加载时间缩短一般。(更新前大概是3.5s,更新后为1.5s左右,和表的数量有直接关系),并且在IIS休眠之后调用,速度也大大加快。

以上的代码只适应于EF6.2以上版本。6.2一下的版本可参考链接 https://entityframework.net/why-first-query-slow 

参考:

https://codeopinion.com/entity-framework-code-first-model-cache/

https://gist.github.com/davidroth/9886349 手动管理exmx文件,和上述代码的区别是,上述代码每次启动都会更新,该方法会根据时间戳判断是否需要更新。

https://*.com/questions/52376465/entity-framework-6-2-very-slow-first-startup-and-efinteractiveviews/52405059#52405059