EF启动极慢-15分钟前段时间我创建了一个系统,用户可以使用自定义文件为某些对象定义类别。然后每个对象都有一个基于其类的FieldValue。以下课程:publicclassDbCategory{publicintId{get;放;}[必填]publicstringName{get;放;}[必需]publicTextDbFieldMainField{get;放;}公共列表字段{get;放;}}publicclassDbObject{publicintId{get;放;}publicbyte[]Bytes{得到;放;}[必需]publicDbCategoryCategory{get;放;}publicTextDbFieldValueMainFieldValue{get;放;}publicListFieldsValues{get;放;}}publicabstractclassDbField{publicintId{get;放;}[必填]publicstringName{get;放;}[必需]publicboolRequired{get;放;}}publicclassIntegerDbField:DbField{publicint?最小{得到;放;公共诠释?最大{得到;放;}}publicclassFloatDbField:DbField{publicdouble?最小{得到;放;}公共双?最大{得到;放;}}//...其他一些类型publicabstractclassDbFieldValue{[Key]publicintId{get;放;}[必填]publicDbFieldField{get;放;}[JsonIgnore]公开}}publicclassIntDbFieldValue:DbFieldValue{publicint?IntValue{得到;放;}publicoverridestringValue{get{returnIntValue?.ToString();}set{if(value==null)IntValue=null;否则IntValue=int.Parse(value);}}}//和其他FieldValue类型在我的开发机器(i5、16bgram和ssd驱动器)数据库(在SqlExpress中)有4个类别,每个类别有5-6个字段,10k条记录,第一次查询大约需要15s第一个查询是varresult=db.Objects.Include(s=>s.Category).Include(s=>s.Category.MainField).Include(s=>s.MainFieldValue.Field).Include(s=>s.FieldsValues.Select(f=>f.Field)).Where(predicate??AlwaysTrue).ToArray();这样做是为了将所有内容都加载到内存中,然后我处理缓存列表并将更改写入数据库。我这样做是因为用户可以在每个FieldValue上使用过滤器执行搜索。每次查询数据库然后进行认证要慢得多——但这部分工作正常。问题发生在后面。有的客户定义6个类别,每个类别20+字段,存储70k+条记录,启动时间有时超过15分钟。之后,5k和50k速度没有区别。我发现的每项改进EFCodeFirst启动时间的技术主要考虑视图创建缓存、ngeningEF等,但在这种情况下,启动时间在添加更多记录后增加,而不是添加更多实体类型。我意识到这是由架构的复杂性引起的,但有没有办法加快速度?幸运的是,这是一个Windows服务,所以一旦启动,它会持续数周,但仍然存在。我应该在第一次加载时删除EF并在普通SQL中执行吗?我应该分批进行吗?我应该将EF更改为nHibernate吗?或者是其他东西?在执行此行期间,在虚拟服务器上,此程序会占用CPU(不是SQL服务器,而是我的应用程序)。我试过只加载对象,然后加载它们的属性。这在小型数据库上稍快(但不是显着),但在大型数据库上较慢。任何帮助表示赞赏,即使答案是“等待”。我设法通过以下技巧将EF的总启动时间减少了3倍:将框架更新为6.2并启用模型缓存:);}}尽早从新线程调用ctx.Database.Initialize()。这仍然需要3-4秒,但由于它发生在其他事情上,所以它有很大帮助。实体以合理的顺序加载到EF缓存中。之前只是在Include之后写了Include,翻译过来就是多重join。我在一些博客文章中发现了一个“经验法则”,即最多两个链接(包括EF)表现相当好,但每个链接都会大大减慢一切。我还找到了一篇显示EF缓存的博文:OnceagivenentityisloadedwithIncludeorLoad,itwillautomaticallyputintheappropriateproperty(theunionofbloggerobjectsiswrong)。所以我这样做了:using(vardb=newMyContext()){db.Fields.Load();db.Categories.Include(c=>c.MainField).Include(x=>x.Fields).Load();db.FieldValues.Load();返回db.Objects.Include(x=>x.MainFieldValue.Field).ToArray();这比包含问题中的数据快6倍。我认为一旦先前加载了实体,EF引擎就不会为相关对象调用数据库,它只是从缓存中获取它们。我还在我的上下文构造函数中添加了这个:Configuration.LazyLoadingEnabled=false;Configuration.ProxyCreationEnabled=false;效果几乎不明显,但可能在庞大的数据集中发挥更大的作用。我还看过RowanMiller对EFCore的介绍,我将在下一个版本中切换到它-在某些情况下它比EF6快5-6倍。我希望这可以帮助别人。以上就是C#学习教程:EF启动速度极慢——15分钟全部内容分享。收藏不代表立场,如涉及侵权,请点击右侧联系管理员删除。如需转载请注明出处:
