jle*_*lew 1 memory entity-framework metadata edmx
我有一个EF 4.2 EDMX模型,我在多租户应用程序中使用它.我连接到大约100个使用相同EDM模型的数据库.第一次访问每个数据库时,我的工作集上升了大约12Mb,这似乎主要由EDM元数据缓存占用.内存使用率永远不会下降.我认为元数据/查询缓存可以共享,因为它是相同的模型.
寻找减少我的内存占用的建议,但我怀疑我无法控制它.
注意:同样的场景不是CodeFirst的问题(我们也在使用它),但我们有很多代码仍然使用EDMX模型,现在无法将其转换.
谢谢!
我相信你可以通过自己缓存MetadataWorkspace来获得你想要的东西.这基本上是DbContext在使用Code First时在内部执行的操作.这并不容易,但我制定了一个我认为应该工作的快速原型.
这里的基本思想是让EF创建一次MetadataWorkspace,然后缓存它并在每次需要创建上下文实例时显式使用它.这显然仅在每个上下文实例使用相同模型时才有效 - 即相同的EDMX.为了完成这项工作,我创建了一个处理缓存的派生ObjectContext:
public class SingleModelCachingObjectContext : ObjectContext
{
private static readonly object WorkspaceLock = new object();
private static MetadataWorkspace _workspace;
public SingleModelCachingObjectContext(string connectionStringName)
: base(CreateEntityConnection(connectionStringName))
{
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
((EntityConnection)Connection).StoreConnection.Dispose();
}
}
private static EntityConnection CreateEntityConnection(string connectionStringName)
{
lock (WorkspaceLock)
{
if (_workspace == null)
{
_workspace = new EntityConnection("name=" + connectionStringName).GetMetadataWorkspace();
}
}
var builder =
new DbConnectionStringBuilder
{
ConnectionString = ConfigurationManager.ConnectionStrings[connectionStringName].ConnectionString
};
var storeConnection = DbProviderFactories.GetFactory((string)builder["provider"]).CreateConnection();
storeConnection.ConnectionString = (string)builder["provider connection string"];
return new EntityConnection(_workspace, storeConnection);
}
}
Run Code Online (Sandbox Code Playgroud)
然后,您可以通过在DbContext类上创建构造函数来使用它,如下所示:
public MyDbContext(string connectionStringName)
: base(new SingleModelCachingObjectContext(connectionStringName),
dbContextOwnsObjectContext: true)
{
}
Run Code Online (Sandbox Code Playgroud)
这是它的工作原理.当您创建DbContext的实例时,它会依次创建一个SingleModelCachingObjectContext实例,该实例将传递您要使用的EF连接字符串的名称.它还告诉DbContext在处理DbContext时处理这个ObjectContext.
在SingleModelCachingObjectContext中,EF连接字符串用于创建MetadataWorkspace,并在创建后将其缓存在静态字段中.这是一个非常简单的缓存和简单的线程安全锁定 - 随意使它更适合您的应用程序的需求.
获得MetadataWorkspace后,现在将解析EF连接字符串以获取存储连接字符串和提供程序.然后,这用于创建正常的商店连接.
存储连接和缓存的MetadataWorkspace用于创建EntityConnection,然后创建将使用缓存的MetadataWorkspace而不是使用常规缓存机制的ObjectContext.
此ObjectContext用于支持DbContext.重写Dispose方法,以便存储连接不会泄漏.当处理DbContext时,它将处理ObjectContext,它将依次调用Dispose并将处理存储连接.
除了确保它运行之外,我还没有真正测试过这个.知道它是否真的有助于你的内存使用问题,这将是非常有趣的.
| 归档时间: |
|
| 查看次数: |
1868 次 |
| 最近记录: |