【问题标题】:LinqToSql InsertOnSubmit memory leak?LinqToSql InsertOnSubmit 内存泄漏?
【发布时间】:2009-11-19 22:44:52
【问题描述】:

我试图在我的 C# 应用程序中隔离“内存泄漏”的来源。此应用程序使用 SQL Server 中的 image 列类型将大量可能较大的文件复制到数据库中的记录中。我正在使用 LinqToSql 和关联对象进行所有数据库访问。

主循环遍历文件列表并插入。在删除了很多样板和错误处理之后,它看起来像这样:

foreach (Document doc in ImportDocs) {
    using (var dc = new DocumentClassesDataContext(connection)) {
        byte[] contents = File.ReadAllBytes(doc.FileName);

        DocumentSubmission submission = new DocumentSubmission() {
            Content = contents,
            // other fields
        };

        dc.DocumentSubmissions.InsertOnSubmit(submission);  // (A)
        dc.SubmitChanges();                                 // (B)
    }
}

在整个输入上运行此程序会产生最终的OutOfMemoryException。 CLR Profiler 显示 99% 的堆由与文件大小相对应的大型 byte[] 对象组成。

如果我同时注释 A 和 B 行,这个泄漏就会消失。如果我只取消注释 A 行,泄漏就会回来。我不明白这是怎么可能的,因为dc 是为循环的每次迭代处理的。

有没有人遇到过这种情况?我怀疑直接调用存储过程或进行插入将避免这种泄漏,但我想在尝试其他方法之前了解这一点。怎么回事?

更新

在 (B) 行之后包含 GC.Collect(); 似乎对任何情况都没有重大改变。这并不让我感到惊讶,因为 CLR Profiler 显示了大量的 GC 事件而没有明确诱导它们。

【问题讨论】:

  • 您是否尝试过调用垃圾回收。也许不是每次都调用它,但至少要调用几次。不说是解决办法,只是好奇测试一下。
  • Yuriy:看起来没什么区别。查看我的更新。
  • 不记得 CLR 探查器是否会让您跟踪大字节 [] 的根 - 这至少可以告诉您是什么阻碍了它们。我通常使用 DevPartner Studio 的分析器,它有助于追踪这类问题。
  • 奇怪-我只是尝试在本地复制它并且它工作正常(我在图像类型的列中做了几千行约 2M 字节 [])而没有增加进程的内存占用( ~14M 在整个运行时稳定)。您是否有可能在您的实体类型上定义了一些导致恶作剧的部分方法?
  • 嗯。我没有闲置的 2300 美元,但我会记住这一点。

标签: c# linq-to-sql memory-leaks out-of-memory


【解决方案1】:

您在哪个操作系统上运行它?您的问题可能与 Linq2Sql 无关,而与操作系统如何管理大内存分配有关。例如,Windows Server 2008 在管理内存中的大型对象方面比 XP 好得多。我遇到过处理大文件的代码在 XP 上泄漏但在 Win 2008 服务器上运行良好的情况。

HTH

【讨论】:

    【解决方案2】:

    我不完全明白为什么,但是制作迭代变量的副本修复了它。据我所知,LinqToSql 以某种方式在每个 Document 中制作了 DocumentSubmission 的副本。

    foreach (Document doc in ImportDocs) {
        // make copy of doc that lives inside loop scope
        Document copydoc = new Document() {
            field1 = doc.field1,
            field2 = doc.field2,
            // complete copy
        };
    
        using (var dc = new DocumentClassesDataContext(connection)) {
            byte[] contents = File.ReadAllBytes(copydoc.FileName);
    
            DocumentSubmission submission = new DocumentSubmission() {
                Content = contents,
                // other fields
            };
    
            dc.DocumentSubmissions.InsertOnSubmit(submission);  // (A)
            dc.SubmitChanges();                                 // (B)
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-10-08
      • 2013-01-20
      • 2011-10-31
      • 2019-08-10
      • 2013-06-24
      • 2011-03-22
      相关资源
      最近更新 更多