jas*_*son -1 c# dispose memory-management list out-of-memory
我有这样的代码:
var myList = db.Table1.ToList();
/*doing some operations on the list*/
var myList = db.Table2.ToList();
/*again doing some operations on the list*/
var myList = db.Table3.ToList(); // I'm getting out of memory exception here.
Run Code Online (Sandbox Code Playgroud)
我不能按页检索数据,因为我需要一次所有的表.在加载另一个表之前,如何处理(我的意思是释放该列表所公开的空间)列表?谢谢.
编辑:
我加载后,实际上是从myList生成了很多(有时是数千个)子列表.所以我真的需要学习如何释放列表.
编辑2:这是我的完整Stacktrace:
at System.Collections.Generic.List`1.set_Capacity(Int32 value)
at System.Collections.Generic.List`1.EnsureCapacity(Int32 min)
at System.Collections.Generic.List`1.Add(T item)
at System.Data.Entity.Core.Objects.EntityEntry.TakeSnapshot(Boolean onlySnapshotComplexProperties)
at System.Data.Entity.Core.Objects.Internal.SnapshotChangeTrackingStrategy.TakeSnapshot(EntityEntry entry)
at System.Data.Entity.Core.Objects.Internal.EntityWrapper`1.TakeSnapshot(EntityEntry entry)
at System.Data.Entity.Core.Objects.ObjectStateManager.AddEntry(IEntityWrapper wrappedObject, EntityKey passedKey, EntitySet entitySet, String argumentName, Boolean isAdded)
at System.Data.Entity.Core.Common.Internal.Materialization.Shaper.HandleEntityAppendOnly[TEntity](Func`2 constructEntityDelegate, EntityKey entityKey, EntitySet entitySet)
at System.Data.Entity.Core.Common.Internal.Materialization.Coordinator`1.ReadNextElement(Shaper shaper)
at System.Data.Entity.Core.Common.Internal.Materialization.Shaper`1.SimpleEnumerator.MoveNext()
at System.Data.Entity.Internal.LazyEnumerator`1.MoveNext()
at System.Collections.Generic.List`1.InsertRange(Int32 index, IEnumerable`1 collection)
at System.Collections.Generic.List`1.AddRange(IEnumerable`1 collection)
at WebApplication2.MyMethod in line 2292
at WebApplication2.Controllers.MyController.MyActtion(String myString) in line 137
at System.Web.Mvc.ActionMethodDispatcher.Execute(ControllerBase controller, Object[] parameters)
at System.Web.Mvc.ReflectedActionDescriptor.Execute(ControllerContext controllerContext, IDictionary`2 parameters)
at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod(ControllerContext controllerContext, ActionDescriptor actionDescriptor, IDictionary`2 parameters)
at System.Web.Mvc.Async.AsyncControllerActionInvoker.<BeginInvokeSynchronousActionMethod>b__39(IAsyncResult asyncResult, ActionInvocation innerInvokeState)
at System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncResult`2.CallEndDelegate(IAsyncResult asyncResult)
at System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncResultBase`1.End()
at System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeActionMethod(IAsyncResult asyncResult)
at System.Web.Mvc.Async.AsyncControllerActionInvoker.AsyncInvocationWithFilters.<InvokeActionMethodFilterAsynchronouslyRecursive>b__3d()
at System.Web.Mvc.Async.AsyncControllerActionInvoker.AsyncInvocationWithFilters.<>c__DisplayClass46.<InvokeActionMethodFilterAsynchronouslyRecursive>b__3f()
Run Code Online (Sandbox Code Playgroud)
根据帖子评论中的其他说明,这db是EF DbContext派生的类变量,在3个调用之间共享.并且Table1,Table2并且Table3是DbSet该环境中的实例.
使用时会发生的情况var myList = db.Table1.ToList()是,除了读取内存中的表并填写列表外,EF DbContext还会DbSet.Local使用相同的对象(所谓的跟踪)填充内部集合,以便能够检测并应用您所做的更改(最终)到底层对象.
这就是问题所在.事件如果Clear,设置null的myList变量,内部缓存(列表)仍持有所有这些对象,最终导致了OutOfMemoryException在一些点.
因此,如果您不打算修改返回的对象并将它们保存回数据库,DbContext那么通过使用所谓的无跟踪查询来完全消除内部缓存:
var myList = db.Table1.AsNoTracking().ToList();
Run Code Online (Sandbox Code Playgroud)
或者清理(Dispose并设置为null)并db = new YourDbContext()为每个列表进程使用新的新上下文().
当然,您可以将上述内容与注释中提到的其他技术结合使用,以清理自己的列表变量.