我相信你可以通過自己緩存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);
}
}
你會再通過像這樣在你的DbContext類創建一個構造函數中使用這樣的:
public MyDbContext(string connectionStringName)
: base(new SingleModelCachingObjectContext(connectionStringName),
dbContextOwnsObjectContext: true)
{
}
這是如何工作的。當您創建DbContext的實例時,它會依次創建一個SingleModelCachingObjectContext的實例,傳遞要使用的EF連接字符串的名稱。它還告訴DbContext在處理DbContext時處置這個ObjectContext。
在SingleModelCachingObjectContext中,EF連接字符串用於創建MetadataWorkspace並在創建後將其緩存在靜態字段中。這是非常簡單的緩存和簡單的線程安全與鎖 - 隨意使其更適合您的應用程序的需求。
在獲得MetadataWorkspace後,現在解析EF連接字符串以獲取商店連接字符串和提供商。然後這用於創建一個正常的商店連接。
商店連接和緩存的MetadataWorkspace用於創建一個EntityConnection,然後是一個ObjectContext,它將使用緩存的MetadataWorkspace,而不是使用正常的緩存機制。
此ObjectContext用於備份DbContext。 Dispose方法被覆蓋,所以商店連接不會泄漏。當DbContext被處置時,它將處理ObjectContext,它將依次調用Dispose並處理存儲連接。
我沒有真正測試過這個以確保它運行。知道它是否確實有助於解決內存使用問題將會非常有趣。
你看過跟蹤與無跟蹤效果嗎?或者你總是需要跟蹤? – 2012-03-03 18:37:05
我們再也不需要跟蹤,但它似乎不有所作爲無論是在與否。無論如何,當GC運行時,應該清理這種內存,我想。 – jlew 2012-03-03 18:51:38