关于 Linq to EF 的内存泄漏问题
查到一些解决方案:
1, http://www.codethinked.com/keep-your-iqueryable-in-check
自定义常用方法,屏蔽IQuery功能。这个好像有点靠谱。但麻烦。
2,http://stackoverflow.com/questions/123057/how-do-i-avoid-a-memory-leak-with-linq-to-sql
这个看起来是应对 ObjectContext的。
这个看起来简单些 ,用using.
4, 直接用using的方式
using(dbcontext)
{
}
5, http://blog.robustsoftware.co.uk/2008/11/clearing-cache-of-linq-to-sql.html
这个针对 DataContext的一个扩展方法。
最后没有更好的解决办法。
/******************************Edit 2014-1-25**************************************************************/
最后在分析了DbContext的源代码以后,发现了其中的奥秘。
首先DbContext本身是对于ObjectContext的一个包装,在使用IQueryable以后会将Enitiy存于 objectStateManager ,在快速的循环中,_unchangedEntityStore不会被释放,一直被缓存,所以呢?你会发现程序的内存在不断的上涨,这不应该算是内存泄漏。 由于 _unchangedEntityStore 中的值变得越来越大,程序在查询前先去 _unchangedEntityStore 中查找,由于Dictionary<EntityKey, EntityEntry> 在很大的情况下,查询性能会急剧下降,所以程序变慢。 直到慢得你无法忍受。
下面是基本代码。
public class Class1
{
public static void Test()
{
Domain.Entities.Models.passportContext context =
new Domain.Entities.Models.passportContext("passportContext");
context.Configuration.ProxyCreationEnabled = false;
context.Configuration.LazyLoadingEnabled = false;
var start = int.MaxValue;
var om = ((IObjectContextAdapter)context).ObjectContext.ObjectStateManager;
om.ObjectStateManagerChanged += om_ObjectStateManagerChanged;
while (true)
{
var list = context.UserSources.OrderByDescending(x => x.UserId).Where(x => x.UserId < start).Take(100).ToList();
ObjectContext oc = ((IObjectContextAdapter)context).ObjectContext;
var m = oc.ObjectStateManager;
var a = list.First();
var count = GetUnchangedCount(context);
var mth = m.GetType().GetMethod("GetObjectStateEntriesCount", BindingFlags.Instance | BindingFlags.NonPublic);
var unchanged = mth.Invoke(m, new object[] { EntityState.Unchanged });
if (a.UserId % 4 == 0)
{
a.FromSite += 1;
context.Entry(a).State = System.Data.EntityState.Modified;
}
count = GetUnchangedCount(context);
ClearUnchangedCache(context);
Console.WriteLine(a.UserId);
//ClearCache(context);
start = a.UserId;
}
}
static void om_ObjectStateManagerChanged(object sender, System.ComponentModel.CollectionChangeEventArgs e)
{
Console.WriteLine("[]" + e.Action + "" + e.Element.GetType() + "::" + e.Element);
}
public static void ClearCache(DbContext context)
{
ObjectContext oc = DbContext2ObjectContext(context);
const BindingFlags flags = BindingFlags.GetField | BindingFlags.NonPublic | BindingFlags.Instance;
var c = oc.GetType().GetField("_cache", flags);
//var value = c.GetValue(oc);
c.SetValue(oc, null);
//value = c.GetValue(oc);
}
static int GetUnchangedCount(DbContext context)
{
var objectStateManager = DbContext2ObjectStateManager(context);
var mth = objectStateManager.GetType().GetMethod("GetObjectStateEntriesCount", BindingFlags.Instance | BindingFlags.NonPublic);
var unchanged = mth.Invoke(objectStateManager, new object[] { EntityState.Unchanged });
return (int)unchanged;
}
static ObjectContext DbContext2ObjectContext(DbContext context)
{
return ((IObjectContextAdapter)context).ObjectContext;
}
static ObjectStateManager DbContext2ObjectStateManager(DbContext context)
{
return DbContext2ObjectContext(context).ObjectStateManager;
}
static void ClearUnchangedCache(DbContext context)
{
var objectStateManager = DbContext2ObjectStateManager(context);
const BindingFlags flags = BindingFlags.GetField | BindingFlags.NonPublic | BindingFlags.Instance;
var c = objectStateManager.GetType().GetField("_unchangedEntityStore", flags);
c.SetValue(objectStateManager, null);
}
}
然后发现内存还是疯长。

那就再加一个方法。
static void ClearKeylessEntityCache(DbContext context)
{
var objectStateManager = DbContext2ObjectStateManager(context);
const BindingFlags flags = BindingFlags.GetField | BindingFlags.NonPublic | BindingFlags.Instance;
var c = objectStateManager.GetType().GetField("_keylessEntityStore", flags);
c.SetValue(objectStateManager, null);
}
再看内存,

这样世界顿时安静了下来。
最后说明:
这个方法的确不是一个好的办法,但是由于EF的对象管理机制决定。 人家缓存也有人家缓存的道理。
实际上MS也没有打算让你按这样的方法来用,
用using(dbcontext)
{
…..
}
这样的方式反而是保持了 Kiss。
对于这样的“改进” 会不会有什么影响呢?
这个就再开个文章再来测试了。
关于 Linq to EF 的内存泄漏问题的更多相关文章
- EntityFramework Core依赖注入上下文方式不同造成内存泄漏了解一下?
前言 这个问题从未遇见过,是一位前辈问我EF Core内存泄漏问题时我才去深入探讨这个问题,刚开始我比较惊讶,居然还有这种问题,然后就有了本文,直接拿前辈的示例代码并稍加修改成就了此文,希望对在自学E ...
- Webservice WCF WebApi 前端数据可视化 前端数据可视化 C# asp.net PhoneGap html5 C# Where 网站分布式开发简介 EntityFramework Core依赖注入上下文方式不同造成内存泄漏了解一下? SQL Server之深入理解STUFF 你必须知道的EntityFramework 6.x和EntityFramework Cor
Webservice WCF WebApi 注明:改编加组合 在.net平台下,有大量的技术让你创建一个HTTP服务,像Web Service,WCF,现在又出了Web API.在.net平台下, ...
- 记一次 WinDbg 分析 .NET 某工厂MES系统 内存泄漏分析
一:背景 1. 讲故事 上个月有位朋友加微信求助,说他的程序跑着跑着就内存爆掉了,寻求如何解决,截图如下: 从聊天内容看,这位朋友压力还是蛮大的,话说这貌似是我分析的第三个 MES 系统了,看样子 . ...
- Java进击C#——应用开发之Linq和EF
本章简言 上一章笔者对于WinForm开发过程用到的几个知识点做了讲解.笔者们可以以此为开端进行学习.而本章我们来讲一个跟ORM思想有关的知识点.在讲之前让我们想一下关于JAVA的hibernate知 ...
- TcpListener的异步调用内存泄漏---最近测试结果,没有泄露
我后来加大了client的连接/断开的次数(500,1000),Server端的连接被释放了. 这说明: 1. 此代码是 可以正常工作的. 2.TcpListener/TcpListener的asyn ...
- Erlang 内存泄漏分析
随着项目越来越依赖Erlang,碰到的问题也随之增加.前段时间线上系统碰到内存高消耗问题,记录一下troubleshooting的分析过程.线上系统用的是Erlang R16B02版本. 问题描述 有 ...
- linq和EF查询的用法和区分
我们做项目时,难免会遇到用的不知道是啥,及把linq和EF搞混了 今天我带领大家梳理下思路: 首先说linq查询,然后介绍EF查询 1.linq查询 当我们使用linq查询时,转到定义会调到Query ...
- 【linux】linux下对java程序生成dump文件,并使用IBM Heap Analyzer进行分析,查找定位内存泄漏的问题代码
1.首先,java程序启动在linux,怎么生成dump文件? 1>第一步,首先你需要得到java程序的PID,最简单的方法使用如下命令 ps -ef|grep java 或者如果是docker ...
- 应用开发之Linq和EF
本章简言 上一章笔者对于WinForm开发过程用到的几个知识点做了讲解.笔者们可以以此为开端进行学习.而本章我们来讲一个跟ORM思想有关的知识点.在讲之前让我们想一下关于JAVA的hibernate知 ...
随机推荐
- Asp.net Web Application 打开 SharePoint 2010 Site 错误 The Web application at could not be found
解决办法如下: 1. 修改项目的.net framework 为3.5 2. Application Pool 选用 Sharepoint App pool 3. 修改 web.config如下: & ...
- 思考ASP.NET网站静态化的利与弊
最近在思考网站要不要进行静态化的问题,在网上收集和整理了有关静态化利与弊的资料,于是写下此博文分享到网络上.由于本人是一名asp.net开发人员,所以本文的观点可能无法涉及到全部方面,但是比较注重于使 ...
- Composer安装(windows)
https://files.cnblogs.com/files/wlphp/Composer-Setup.zip 先下载这个安装包,一直下一步 然后设置composer全局中国景象 composer ...
- 面试题:java实例变量,局部变量,类变量 背1
一.实例变量 也叫对象变量.类成员变量:从属于类由类生成对象时,才分配存储空间,各对象间的实例变量互不干扰,能通过对象的引用来访问实例变量.但在Java多线程中,实例变量是多个线程共享资源,要注意同步 ...
- FacadePattern(23种设计模式之一)
设计模式六大原则(1):单一职责原则 设计模式六大原则(2):里氏替换原则 设计模式六大原则(3):依赖倒置原则 设计模式六大原则(4):接口隔离原则 设计模式六大原则(5):迪米特法则 设计模式六大 ...
- sql注意事项积累
1.一定要记住,SQL 对大小写不敏感! 2.sql中的单引号 '',如果单引号中是字符串,代表是常量 如,select 'b.phoneNumeber' from test; 如果是数字,如'123 ...
- Servlet入门第一天
1. 使用 JavaEE 版的 Eclipse 开发动态的 WEB 工程(JavaWEB 项目) 1). 把开发选项切换到 JavaEE 2). 可以在 Window -> Show View ...
- javascript总结18:javascript DOM简介
1 HTML DOM 使 JavaScript 有能力对 HTML 事件做出反应.在事件发生时,执行JavaScript 方法,做出交互. 2 格式: onclick=JavaScript脚本 3 H ...
- Matlab和Python用于深度学习应用研究哪个好?
Matlab和Python都有一些关于深度学习的开源的解决方案(caffe\DeepMind\TensorFlow),基于哪个开展应用研究好?
- Js杂谈-插件包读后感
最近有幸得到了一份项目上的前端封装的插件库代码,花了一个下午时间,仔细地研读了一下.对于我很想做自己的类库,搞自己的组件包很有启蒙意义. 相比较我之前阅过的框架或是类库,这份比较简单. 项目是jQue ...