37

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

在此处输入图像描述

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

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

编辑:一些相关链接:

EDIT2:现在他们刚刚开源了代码,看来这一行:

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

4

3 回答 3

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-必须预先生成视图-ef6/

于 2012-05-25T16:06:09.490 回答
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-画廊/

于 2012-05-26T22:47:16.390 回答
1

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

于 2014-09-15T10:04:32.983 回答