【问题标题】:Entity Framework - Excessive data loads with Views实体框架 - 使用视图加载过多的数据
【发布时间】:2011-11-23 16:14:57
【问题描述】:

我们在实体之间导航时遇到问题,其中一个实体基于视图。 问题是我们什么时候去

TableEntity.ViewEntity.Where(x => x.Id == Id).FirstOrDefault())

它在后台加载视图中的所有记录,这不是我们想要或期望的。

我们去的时候

_objectContext.TableEntityView
    .Where(x => x.TableObjectId == TableObjectId && x.Id == Id)

然后它只加载我们所期望的一行

简而言之,使用导航属性会导致大量数据负载——就像查询正在提前实现一样。

我们将 EF 4 与 SQL 2005 数据库一起使用。这些视图用于提供聚合信息,EF 在没有大数据负载的情况下无法轻松完成(讽刺的是)。我们手动构建了 1:视图之间的许多关联。

那么为什么我们在第一个实例中获得了大数据负载,而在第二个实例中却没有呢?

非常感谢所有/任何帮助

【问题讨论】:

    标签: c# sql-server-2005 entity-framework views


    【解决方案1】:

    这就是导航集合在 EF 中的工作方式:访问集合会加载所有实体,之后您运行的任何 linq 查询只需查询内存中的对象。我认为除了您已经完成的自定义查询之外,您无能为力。

    FWIW 我听说 NHibernate 支持更细粒度的导航加载,但该功能尚未进入实体框架。

    编辑

    来自 Ladislav Mrnka 的This answer 展示了从 CTP 时代开始可能解决您的问题的方法。不确定从那以后是否有任何变化。它使用 DbContext,因此您仍然无法只通过导航属性,但它可能与您将要获得的一样接近。

    int count = context.Entry(myAccount)
                       .Collection(a =>  a.Orders).Query().Count();`
    

    或者对于你的情况,我猜它会是

    TableEntityView obj = context.Entry(TableEntity)
                                 .Collection(a => a.ViewEntity)
                                 .Query().FirstOrDefault(x => x.Id == Id);
    

    【讨论】:

    • 谢谢@Adam Rackis。但如果我去 Table1.Table2.Where(x => x.Id == Id) 它肯定不会加载 Table2 中的所有内容。我的理解是因为在幕后它是 IQueryable 而不是 IEnumerable 然后它将所有内容一次性发送到服务器 - 当您意识到查询时触发,即使用 ToList()。否则导航属性在 EF 中不可用。
    • 是的,你是对的。导航属性不是 IQueryable。在大多数情况下,开箱即用的行为可能是最好的。如果您需要更细粒度的控制,也许 NH 对您来说是一个更好的 ORM? (这是来自一个巨大的 EF 粉丝,顺便说一句)
    • @Tim,另请参阅我的编辑。这可能使用 DbContext 实现,但仅通过对象导航属性仍然​​无法实现
    • 这看起来很不错。我们使用的是 EF 4,但看起来这可能值得升级到 EF 4.1。我们这里的问题是我们正在过滤两个参数 - 一个通过导航属性隐含,一个通过查询 - 我们在导航中走错了路,即我们选择了最终以相当大的集合结束的导航某种方式。我确信这是风景
    • @Tim:你不需要升级。 EFv4 也支持这一点,但 syntax is different(更糟糕)它有一些缺陷,因为您必须显式打开/关闭延迟加载以避免大量查询。
    【解决方案2】:

    我在 EntityFramework 生成 SQL 的方式上遇到了一些问题,所以首先我建议您使用 LinqPad 和以下一个或多个:EntityFramework profiler(软件付费)、SQL Profiler(假设您正在使用 SQL Server)和/或 EFTracingProvider

    我遇到过在某些查询中多次内联同一个表的问题,因此使用这些工具通常有助于找出导致问题的原因。

    我尝试过的一些事情通常会使一些查询运行得更快:

    编写完整的 Linq 查询而不是使用 Lambda 表达式:它们通常更易于阅读,并且看起来更像 sql,因此更容易查看您的代码和生成的 sql 之间的关系

    EntitySet.Include(x=>x.Property)

    这告诉 Linq2Entities 在查询中包含该属性

    【讨论】:

      猜你喜欢
      • 2013-08-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-04-23
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多