【问题标题】:EntityFramework - Sum() Causing OutOfMemoryExceptionEntityFramework - Sum() 导致 OutOfMemoryException
【发布时间】:2014-08-05 16:12:07
【问题描述】:

我有一个 MVC 应用程序,它使用 EntityFramework 连接到 MS SQL Server 2012。我正在尝试检索存储在 Documents 表中的所有文档的总文件大小。

我正在使用以下代码:

this.Documents.Sum(x => x.FileSize);

Documents 的类型为 EntityCollection<Document>。该操作需要超过 1.6 分钟才能完成,此时它会崩溃并显示

Exception of type 'System.OutOfMemoryException' was thrown.

当然,这与直接通过 SQL Server Management Studio 执行时只需几毫秒即可完成 SELECT SUM(FileSize) FROM Documents 的操作相同。

不管怎样,总大小为 816mb,包括 1,661 个文档,所以它并不十分庞大。

【问题讨论】:

  • 您是否附加了 sql profiler 并检查了正在发送的查询?
  • 你可能在 this.Documents 之前的某个地方做一个 ToList() 吗?因为如果它已经在内存中,那么 Sum 将在客户端执行...
  • 如果它只是总和尝试 this.Documents.Select(c => c.FileSize).Sum() 代替,这样你就不会获取太多数据
  • 或者你可以试试this.Documents.Select(c => c.Sum(i => i.FileSize))

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


【解决方案1】:

我似乎很清楚EntityCollection<Document> 正在懒惰地加载数据库中的每个Document。如果您的 Document 实体具有可以解释一切的 blob 数据。假设你有一个DbContext 的实例,我会检索一个DbSet<Document> 的实例,这样你就可以这样写:

var result = (from d in documents
              select new { Size = d.FileSize }).Sum(x => x.Size);

【讨论】:

    【解决方案2】:

    如果您想对数据库执行 Sum() 查询,请确保您的 Documents 属性是 IQueryable<Document> 而不是 IEnumerable<Document>。前者会将您的 LINQ 查询转换为 SQL(即,它将被转换为 SELECT SUM(FileSize)),而后者将是 LINQ-to-objects,这将在内存中完成。

    更多信息可以参考这个答案:Returning IEnumerable<T> vs. IQueryable<T>

    【讨论】:

      【解决方案3】:

      该问题似乎是由延迟加载引起的,如前面的答案中所述,但是建议的方法似乎都不起作用。但是,创建一个新的数据库实体并直接查询似乎可以正常工作:

      MyEntities entities = new MyEntities();
      decimal size = entities.Documents.Where(x => x.UniverseID == this.ID).Sum(x => x.FileSize);
      

      我不确定有什么区别,但它似乎有效!

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-06-14
        • 1970-01-01
        • 2016-12-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多