使用:
关注点:内存使用
在我们目前正在进行的项目中,可能是我们的第一个更大的项目,我们经常阅读来自CSV导入的更大块数据,这些数据可能会在很长一段时间内保持不变。
除非有人明确地重新导入CSV数据,否则它们保证是相同的,这发生在我们项目的多个地方,类似的方法用于一些常常由用户阅读的常规文档。我们决定将这些数据缓存在HttpRuntime缓存中。
它是这样的,我们拉大约15,000条记录,主要由字符串组成。
//myObject and related methods are placeholders
public static List<myObject> GetMyCachedObjects()
{
if (CacheManager.Exists(KeyConstants.keyConstantForMyObject))
{
return CacheManager.Get(KeyConstants.keyConstantForMyObject) as List<myObject>;
}
else
{
List<myObject> myObjectList = framework.objectProvider.GetMyObjects();
CacheManager.Add(KeyConstants.keyConstantForMyObject, myObjectList, true, 5000);
return myObjectList;
}
}
上述方法的数据检索非常简单,如下所示:
public List<myObject> GetMyObjects()
{
return context.myObjectsTable.AsNoTracking().ToList();
}
关于代码结构可能有些事要说,但目前我并不关心这一点。
我一看到内存使用率很高就开始分析我们的项目,并发现许多部分可以优化我们的代码。我以前从未面对300个同时用户,我们自己完成的内部测试不足以显示内存问题。我已经突出显示并修复了许多内存泄漏,但我想了解一些与Entity Framework相关的未知数。
鉴于以上示例,并使用ANTS Profiler,我注意到' myObject '和其他类似对象引用了许多 System.Data.Entity.DynamicProxies .myObject,还有很多 EntityKeys ,它们保留整数。他们没有太多,但他们的数量相对较高。
例如,124个“ myObject ”实例引用了近300个System.Data.Entity.DynamicProxies。
通常它看起来像这样,无论对象是什么: 一些缓存条目,我缓存的一些对象,我现在注意到它们中的许多已经从dbContext事先缓存,动态代理和objectContext中分离出来。我不知道如何解开它们。
我做了一些研究,发现我可能正在缓存与这些对象相关的实体框架。我用 NoTracking 来提取它们但是内存中仍然存在那些可能还有其他东西的DynamicProxies。
重要:我观察到一些ObjectContext(74)的实时实例,慢慢增长,但没有我的unitOfWork实例持有dbContext。这些似乎可以根据要求妥善处理。
我知道如何从我的dbContext中分离,附加或修改条目的状态,dbContext包含在unitOfWork中,我经常这样做。然而,这似乎不够,或者我要求不可能。
答案 0 :(得分:4)
您可以尝试使用具有SELECT方法的特定属性的非实体类。
public class MyObject2 {
public int ID { get; set; }
public string Name { get; set; }
}
public List<MyObject2> GetObjects(){
return framework.provider.GetObjects().Select(
x=> new MyObject2{
ID = x.ID ,
Name = x.Name
}).ToList();
);
}
由于您将存储普通的c#对象,因此您不必担心动态代理。你根本不需要调用任何东西。此外,您只能存储少数属性。
即使你禁用跟踪,你也会看到动态代理,因为EF使用从你的类派生的动态类,它为实体存储额外的元数据信息(关系,例如外键的名称等等)。
答案 1 :(得分:1)
这里减少内存的步骤:
new
上下文
不要尝试从上下文中删除内容。或者将其设置为分离。
它像电话盒里的屁一样挂着
例如context = new MyContext.
使用(var context = new Mycontext){....}
//短暂的上下文是最佳实践
this.Configuration.LazyLoadingEnabled = false; this.Configuration.ProxyCreationEnabled = false; //<<<<<<<<<<< THIS one this.Configuration.AutoDetectChangesEnabled = false;
如果您仍然觉得他们正在占用内存,您可以禁用代理。
但如果您首先将using
应用于上下文,则可能会出现这种情况。
答案 2 :(得分:0)
我会稍微重新设计一下解决方案:
我会移动它,每个缓存项都有一个条目。
我会使用Appfabric Caching,也是MS,也是免费的。
我会在应用程序启动时调用它,然后当用户需要时所有数据都在内存中
为此,我将使用实体数据阅读器http://msdn.microsoft.com/en-us/library/system.data.entityclient.entitydatareader(v=vs.110).aspx
另见: