实体框架内存未发布

时间:2014-01-27 11:09:26

标签: c# entity-framework entity-framework-6

我在Entity Framework 6.0.2,.Net 4.5.1中使用了一个非常简单的asp.net mvc应用程序:

public class HomeController : Controller
{
   public ActionResult Index()
   {
      int count;
      using (var db = new LocalContext())
      {
         count = db.Counters.Count();
      }
      return View(count);
   }
}

public class Counter
{
   public int Id { get; set; }
}

public class LocalContext : DbContext
{
   public DbSet<Counter> Counters { get; set; }
}

如果我对它进行负载测试,我最终会得到Out of Memory异常。 (tinyget -srv:localhost -port:<port> -uri:/home/index/ -threads:30 -loop:5000)。在性能监视器中,我看到第2代Heap稳步增长。如果我使用较小的循环值(比如500),则大小会增加,直到tinyget停止。然后堆大小保持不变(至少20分钟,之后我停止了服务器)。

我做错了什么?

修改

所以我尝试了Simon Mouriers的建议并省略了EF代码。然后我没有记忆问题。所以我想,也许如果我使用Release而不是Debug,它会有所作为。它做到了!内存在一段时间后被释放,我可以在网站上施加高负荷。然后我切换回Debug,看看我是否可以获得更多信息......即使在调试模式下也没有问题了。 FML,我工作了一天,现在我再也无法重现它了。

5 个答案:

答案 0 :(得分:4)

在您的情况下,继承自DbContext的内部托管类需要实现IDisposable并在LocalContext内部添加以下内容:

public void Dispose()
{
    this.Dispose(true);
    GC.SuppressFinalize(this);
}

protected virtual void Dispose(bool disposing)
{
     if (disposing)
     {
        // Manage any native resources.
     }
   //Handle any other cleanup.
}

如果没有专门覆盖对dispose的调用,则using语句只会针对基类调用Dispose(),而你需要处理父类和基类。

答案 1 :(得分:0)

这可能不是正确的答案,但我建议保持您的上下文由IoC容器管理。并使用TrasientScope或PerHttpRequest范围添加它(由于ioc容器语法的多样性,未提供示例)。如果您想要一个特定的例子,请回复您想要的DI

答案 2 :(得分:0)

实际上,OutOfMemotyException在这种情况下是正常的,因为垃圾收集器在您完成对象后不会立即发生。在这种情况下,您需要使用GC.Collect()在所有代内存上执行集合,并回收所有无法访问的内存,立即

public class HomeController : Controller
{
   public ActionResult Index()
   {
      int count;
      using (var db = new LocalContext())
      {
         count = db.Counters.Count();
      }

      GC.Collect();
      return View(count);
   }
}

请注意,您不应在生产代码中使用GC.Collect(),因为它会干扰垃圾收集机制。

答案 3 :(得分:0)

我会去创建与DB的类连接..

public class DBconnection : IDisposable
{
    private ChatEntities _db = new ChatEntities();

    protected ChatEntities Db {
        get { return _db; }
    }

    public void Dispose()
    {
        if (_db != null)
        {
            _db.Dispose();
        }
    }
}

然后当你想连接和操作时..让我们称之为DBlogic类..

public class DBlogic : DBconnection
{
       internal void WriteToDB(String str){
          //Do something ...

          Db.SaveChanges();
        }
}

这最终会导致Dispose清空资源..加上它的清洁......至少对我的眼睛来说:D

答案 4 :(得分:0)

我认为您的代码没有任何问题。也许这可能是底层ADO.NET提供程序的问题。您使用的是哪个数据库?

我记得有些单元测试没有发布SQLite数据库文件的问题我最终用这段代码解决了(在我的DbContext类中)

public class LocalContext : DbContext
{
    protected override void Dispose(bool disposing)
    {
        var connection = this.Database.Connection;
        base.Dispose(disposing);
        connection.Dispose();
    }
}

可能无关,但我会尝试一下。