ADO.NET实体抛出OutOfMemoryException。如何防止这种情况

时间:2011-02-28 17:43:19

标签: c# .net memory-management ado.net

基础表在SQL Server 2008 R2中有一个int,guid和Filestream列。文件流显示为byte []。我观察到的是内存消耗不断增加。我该怎么办?

MyEntities bh = new MyEntities ();
foreach (var s in bh.TaskGraphs)
{
    try
    {
        using (var x = new MemoryStream(s.TaskGraph1))
        {
            //var t = TaskGraph.Load(x);
            //Validate(t);
        }
    }
    catch (Exception e)
    {                
    }
}

这是内存使用模式

enter image description here

我现在观察到做bh.TaskGraphs.Select(p => new {p.TaskGraph1,p.StreamId}会使异常消失。是否由于子表链接到此表?

BTW,每个BLOB约为3MB

4 个答案:

答案 0 :(得分:1)

实体框架在实体容器中加载实体,容器具有实体集,该实体集包含从数据库中获取的实体的本地副本。每个实体都有一个对应实体集的引用,整个实体集将保留在内存中,实体集将继续增长,因为您将从数据库加载它。

您必须使用一对一关系将表分成两部分,其中包含主键和其他属性的表以及另一个仅包含主键和blob的表。

接下来在你的for循环中,你应该通过一个新的上下文加载你的blob实体并处理你的字节数组并在for循环结束时销毁你的上下文。或者您也可以从实体容器中分离一个对象,使其可以自由地进行垃圾回收。

在现有代码中,您可以分离将释放其所占用内存的实体。

MyEntities bh = new MyEntities ();
foreach (var s in bh.TaskGraphs)
{
    try
    {
        using (var x = new MemoryStream(s.TaskGraph1))
        {
            //var t = TaskGraph.Load(x);
            //Validate(t);
            bn.Detach(t);
        }
    }
    catch (Exception e)
    {                
    }
}

答案 1 :(得分:0)

没有更多信息很难说,但我想,以下至少是问题的一部分:

  1. TaskGraphs包含很多行,或Filestream列包含大量日期
  2. TaskGraph.Load和/或Validate保留对该数据的引用,因此不会进行垃圾回收。
  3. 对象上下文MyEntitiesFilestream列保留在内存中一段时间​​,然后再将其释放。

答案 2 :(得分:0)

我认为TaskGraph表有很多记录,所以当你调用bh.TaskGraphs时,它会将整个表加载到内存中,并且其中的二进制数据大于可用的内存。 您应该尝试通过另一种方式使用存储过程从数据库加载您想要的记录。 但首先尝试这个:

using(MyEntities bh = new MyEntities())
{
    your code.....
}

答案 3 :(得分:0)

我认为没有一个简单的解决方案。请参阅此相关问题:Handling BLOBs in Entity Framework 4.0 in a stream-fashion