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

发布于 2024-10-19 18:04:47 字数 617 浏览 0 评论 0原文

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)
    {                
    }
}

这是内存使用模式

在此处输入图像描述

我现在观察到执行 bh.TaskGraphs.Select(p => new { p.TaskGraph1, p.StreamId } 使异常消失,是否是由于链接到该表的子表所致

,每个 BLOB 约为 3MB ?

The underlying table has a int, guid and Filestream column in SQL Server 2008 R2. The filestream shows up as byte[]. What I observe is that the memory consumption keeps on increasing. What should I do?

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)
    {                
    }
}

Here's the memory usage pattern

enter image description here

I now observed that doing bh.TaskGraphs.Select(p => new { p.TaskGraph1, p.StreamId } makes the exception go away. Is it due to the child table linked to this table?

BTW, each BLOB is ~ 3MB

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

吹泡泡o 2024-10-26 18:04:47

实体框架将实体加载到实体容器中,并且容器具有一个实体集,其中包含从数据库获取的实体的本地副本。每个实体都有其相应实体集的引用,整个实体集将保留在内存中,并且当您从数据库加载实体集时,实体集将不断增长。

您必须使用包含主键和其他属性的表和仅包含主键和 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)
    {                
    }
}

Entity framework loads entity in an entity container and container has an entity set which contains local copy of entity which was fetched from database. Every entity has a reference of it's corresponding entity set and entire entity set will stay in memory and entity set will be keep on growing as you will load it from database.

You must divide your table into two parts using one to one relationship with table containing primary key and other attributes and another table containing just primary key and blob.

Next in your for loop while you are iterating, you should load your blob entity via a new context and process your byte array and destroy your context at the end of for loop. Or you can also detach an object from entity container that will make it free to e garbage collection.

In your existing code you can detach your entity that will free the memory it is holding.

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)
    {                
    }
}
茶色山野 2024-10-26 18:04:47

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

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

It's hard to say without more info, but I suppose, the following is at least part of the problem:

  1. The table TaskGraphs has a lot of rows or the Filestream column contains a lot of date
  2. TaskGraph.Load and/or Validate keep a reference to that data, so it will not be garbage collected.
  3. The object context MyEntities keeps the Filestream columns in the memory for a certain period of time, before releasing it again.
看春风乍起 2024-10-26 18:04:47

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

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

What i think is TaskGraph table has a lot of records, so when you call bh.TaskGraphs it loads the entire table into memory and the binary data in it bigger than memory available.
You should try to load only records you want from database by using stored procedure so another way.
but first try this:

using(MyEntities bh = new MyEntities())
{
    your code.....
}
想挽留 2024-10-26 18:04:47

我认为对此没有简单的解决方案。请参阅此相关问题:在实体框架中处理 BLOB流媒体时尚 4.0

I don't think there is an easy solution for this. See this related question: Handling BLOBs in Entity Framework 4.0 in a stream-fashion

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文