实体框架初始化是缓慢的 - 我可以做些什么来更快地引导它?

时间:2012-05-25 15:16:13

标签: c# performance entity-framework-4 entity-framework-4.3

我的EF 4.3.1模型有200多个表。最初的启动很糟糕,几分钟。 DotTrace捕获的配置文件暗示了框架深处的一些可怕的算法/可伸缩性选择,正如数百万次调用那里的许多方法和3600万个IEnumerable.Contains()调用所证明的那样。这是一个片段,这是由在数据库上完成的第一个查询触发的(未来的查询不会这样做并且很好)。

enter image description here

我可以对我的模型做些什么来减轻痛苦?我能以某种方式预先编译吗?更好的是,EF团队可以解决这些问题或开源框架,以便我可以吗?或者至少修正Warapper的拼写? :)

编辑:触发此操作的一个特定EF调用基本上是var db = new MyDbContext(); db.Personnel.Where(a => a.Login == login).SingleOrDefault();。此外,EF Migrations Seed()AddOrUpdate可以有效地生成相同的堆栈。可以提供更多上下文的更全面的堆栈跟踪在这里:Fuller Stack Trace

编辑:一些相关链接:

EDIT2:现在他们只是open sourced代码,看来这一行:

//Filter the 1:1 foreign key associations to the ones relating the sets used in these cell wrappers.
oneToOneForeignKeyAssociationsForThisWrapper =
    oneToOneForeignKeyAssociationsForThisWrapper.Where(
        it => (it.AssociationEndMembers.All(endMember => entityTypes.Contains(endMember.GetEntityType()))));

是需要一些工作的人。它可能没有使用O(n ^ 2)算法,但我还没有仔细观察。

EDIT3:令人高兴的是,看起来EF6中的工作正在修复此代码:http://entityframework.codeplex.com/discussions/396130

3 个答案:

答案 0 :(得分:23)

在EF6之前,已知视图生成对于较大型号而言较慢。目前解决方案是使用预生成的视图。这样,您可以在设计时生成视图,并在运行时避免这种工作。为此,请下载EF电动工具并选择“优化实体数据模型”。它会将C#文件添加到包含视图的项目中。不好的一面是,每次模型更改时都需要这样做。注意:要使用该工具生成视图,它将花费大约相同的时间在运行时生成视图(因此有时您需要耐心等待)。以下是可能有用的EF Power Tools帖子:http://blogs.msdn.com/b/adonet/archive/2011/05/18/ef-power-tools-ctp1-released.aspx

修改

最近我创建了一个更方便使用的不同解决方案(注意它只适用于EF6) - http://blog.3d-logic.com/2013/12/14/using-pre-generated-views-without-having-to-pre-generate-views-ef6/

答案 1 :(得分:12)

这是另一种方法。它需要一些手动工作,但实际上可能更适合您想要使用MsBuild的场景。而不是使用Power Tools创建视图(我很遗憾听到它们不适合您),您可以手动创建它们 - 以下是步骤:

  • 首先,您需要为您的上下文获取工件。你需要所有 - csdl,ssdl和msl文件。您可以使用EdmxWriter来获取这些内容。请注意,EdmxWriter返回一个edmx文件,该文件组合了所有三个文件,因此您需要将它们拆分。以下是此步骤的代码(请注意,命名空间特定于EF4,如果您考虑使用EF5和.NET Framework 4.5,则需要相应地更改它们或仅按本地名称而不是完全限定名称选择元素):

    var ms = new MemoryStream();
    using (var writer = XmlWriter.Create(ms))
    {
        EdmxWriter.WriteEdmx(new Context(), writer);
    }

    ms.Position = 0;

    var xDoc = XDocument.Load(ms);

    var ssdl = xDoc.Descendants("{http://schemas.microsoft.com/ado/2009/02/edm/ssdl}Schema").Single();
    var csdl = xDoc.Descendants("{http://schemas.microsoft.com/ado/2008/09/edm}Schema").Single();
    var msl = xDoc.Descendants("{http://schemas.microsoft.com/ado/2008/09/mapping/cs}Mapping").Single();

    ssdl.Save("Context.ssdl");
    csdl.Save("Context.csdl");
    msl.Save("Context.msl");
  • 当您有工件时,您可以使用EdmGen工具生成视图。从这里我们手动完成,您需要从VS命令提示符执行此操作。以下是用于生成视图的命令:
EdmGen /mode:ViewGeneration /incsdl:Context.csdl  /inmsl:Context.msl /inssdl:Context.ssdl /outviews:Context.Views.cs
  • 将生成的文件添加到项目中。

如果要将视图生成与构建系统集成,还有一个有趣的选项 - 使用T4模板。该模板将处理上述步骤。您可以在http://blogs.msdn.com/b/adonet/archive/2008/06/20/how-to-use-a-t4-template-for-view-generation.aspx找到有关此方法的更多详细信息。唯一的问题是该示例不适用于CodeFirst方法,因此需要稍微更改一下,这应该不会很难。

我实际上为Code First创建了T4模板。您可以在我的博文中找到要下载的链接:http://blog.3d-logic.com/2012/05/28/entity-framework-code-first-and-pre-generated-views/

现在可以在Visual Studio代码库中使用这些模板。以下是包含所有详细信息的帖子的链接:http://blog.3d-logic.com/2012/06/13/entity-framework-codefirst-view-generation-templates-on-visual-studio-code-gallery/

答案 2 :(得分:1)

在当前版本的Entity Framework中,视图生成实际上非常快。 (6.1)准备中还有另一个更广泛的缓存解决方案:https://entityframework.codeplex.com/workitem/1876。你可以等待这个补丁被接受,或者,如果你足够勇敢,你可以自己申请。