查到一些解决方案:          

 

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的。

 

3,http://stackoverflow.com/questions/19116851/entity-framework-using-repository-pattern-unit-of-work-and-unity

这个看起来简单些 ,用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 的内存泄漏问题的更多相关文章

  1. EntityFramework Core依赖注入上下文方式不同造成内存泄漏了解一下?

    前言 这个问题从未遇见过,是一位前辈问我EF Core内存泄漏问题时我才去深入探讨这个问题,刚开始我比较惊讶,居然还有这种问题,然后就有了本文,直接拿前辈的示例代码并稍加修改成就了此文,希望对在自学E ...

  2. 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平台下, ...

  3. 记一次 WinDbg 分析 .NET 某工厂MES系统 内存泄漏分析

    一:背景 1. 讲故事 上个月有位朋友加微信求助,说他的程序跑着跑着就内存爆掉了,寻求如何解决,截图如下: 从聊天内容看,这位朋友压力还是蛮大的,话说这貌似是我分析的第三个 MES 系统了,看样子 . ...

  4. Java进击C#——应用开发之Linq和EF

    本章简言 上一章笔者对于WinForm开发过程用到的几个知识点做了讲解.笔者们可以以此为开端进行学习.而本章我们来讲一个跟ORM思想有关的知识点.在讲之前让我们想一下关于JAVA的hibernate知 ...

  5. TcpListener的异步调用内存泄漏---最近测试结果,没有泄露

    我后来加大了client的连接/断开的次数(500,1000),Server端的连接被释放了. 这说明: 1. 此代码是 可以正常工作的. 2.TcpListener/TcpListener的asyn ...

  6. Erlang 内存泄漏分析

    随着项目越来越依赖Erlang,碰到的问题也随之增加.前段时间线上系统碰到内存高消耗问题,记录一下troubleshooting的分析过程.线上系统用的是Erlang R16B02版本. 问题描述 有 ...

  7. linq和EF查询的用法和区分

    我们做项目时,难免会遇到用的不知道是啥,及把linq和EF搞混了 今天我带领大家梳理下思路: 首先说linq查询,然后介绍EF查询 1.linq查询 当我们使用linq查询时,转到定义会调到Query ...

  8. 【linux】linux下对java程序生成dump文件,并使用IBM Heap Analyzer进行分析,查找定位内存泄漏的问题代码

    1.首先,java程序启动在linux,怎么生成dump文件? 1>第一步,首先你需要得到java程序的PID,最简单的方法使用如下命令 ps -ef|grep java 或者如果是docker ...

  9. 应用开发之Linq和EF

    本章简言 上一章笔者对于WinForm开发过程用到的几个知识点做了讲解.笔者们可以以此为开端进行学习.而本章我们来讲一个跟ORM思想有关的知识点.在讲之前让我们想一下关于JAVA的hibernate知 ...

随机推荐

  1. 仿照admin写一个startk组件

    settings.py INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.conten ...

  2. java多线程编程核心技术-笔记

    一.第一章 1.自定义线程类中实例变量针对其他线程有共享和不共享之分,自定义线程中的变量,如果是继承自thread类,则每个线程中的示例变量的更改,不影响其他线程2.当多个线程去访问一个局部变量是会产 ...

  3. struts2中s:iterator的使用(2个list嵌套循环)

    <s:iterator value="packagePlateTbls" id="plateTbls"> <tr> <td cla ...

  4. Web项目开发性能优化解决方案

    web开发性能优化---安全篇 1.ip验证 2.操作日志.安全日志.登录日志 3.SQL注入校验 4.权限管理 5.验证规范(前端.后端.数据库约束) 2014-10-29 08:04   2773 ...

  5. 刷题向》DP》值得一做》关于对DP问题的充分考虑(normal)

    在你辛苦调试一道DP题,遇到瓶颈的时候,你是否感到一股洪荒之力遏制住你的思想,使你给题库贡献了一倍的WA.RE.TLE量,却没有AC过一次? 在这时,你应该考虑的是砸电脑再次重新考虑整个题目,再应对自 ...

  6. LoadRunner简明教程

    LoadRunner是什么 LoadRunner是一个性能测试工具,它最初是Mercury公司的产品,后背HP收购. LoadRunner常用来做什么 l 验证某系统在某环境下是否满足性能需求. l  ...

  7. PCL 平面模型分割

    点云操作中,平面的分割是经常遇到的问题,下面的例子就是如何利用PCL库提拟合出的参数,之后就可以过滤掉在平面附近的点云. #include <iostream> #include < ...

  8. getContextPath、getServletPath、getRequestURI,getRealPath的区别

    假定你的web application 项目名称为news,你在浏览器中输入请求路径: http://localhost:8080/news/main/list.jsp 则执行下面向行代码后打印出如下 ...

  9. SEO网站结构优化

    结构布局优化:用扁平化结构(层次结构超过三层小蜘蛛就不愿意爬了) 控制首页链接数量(中小网站100以内,页面导航.底部导航.锚文字链接等) 扁平化的目录层次(小蜘蛛跳转3次可以到达网站内任何一个内页, ...

  10. 编写高质量代码改善C#程序的157个建议——建议21:选择正确的集合

    建议21:选择正确的集合 要选择正确的集合,首先要了解一些数据结构的知识.所谓数据结构,就是相互之间存在一种或多种特定关系的数据元素的集合. 集合的分类参考下图: 由于非泛型集合存在效率低及非类型安全 ...