自分でMetadataWorkspaceをキャッシュすることで、自分が望むものが得られると思います。これは基本的に、コードファーストを使用するときにDbContextが内部的に行うことです。それは簡単ではありませんが、動作するはずの素早いプロトタイプを作成しました。
ここでの基本的な考え方は、EFにMetadataWorkspaceを一度作成させてからキャッシュし、コンテキストインスタンスを作成する必要があるたびに明示的に使用させることです。これは明らかに、各コンテキストインスタンスが同じモデルを使用している場合、つまり、同じEDMX。
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)
{
}
これは、それがどのように動作するかであるこの作品を作るために、私は、キャッシングを扱う派生のObjectContextを作成しました。 DbContextのインスタンスを作成すると、使用するEF接続文字列の名前で渡されるSingleModelCachingObjectContextのインスタンスが作成されます。また、DbContextには、DbContextが配置されているときにこのObjectContextを破棄するように指示されます。
SingleModelCachingObjectContextでは、EF接続文字列を使用してMetadataWorkspaceを作成し、一度作成した静的フィールドにキャッシュします。これは非常にシンプルなキャッシングであり、ロック付きの単純なスレッドセーフです。アプリのニーズに合わせて自由に設定できます。
MetadataWorkspaceを取得すると、EF接続文字列が解析され、ストア接続文字列とプロバイダが取得されます。これは、通常のストア接続を作成するために使用されます。
ストア接続とキャッシュされたMetadataWorkspaceを使用してEntityConnectionを作成し、次に通常のキャッシュメカニズムを使用する代わりにキャッシュされたMetadataWorkspaceを使用するObjectContextを作成します。
このObjectContextは、DbContextを後退させるために使用されます。 Disposeメソッドは、ストア接続がリークしないようにオーバーライドされます。 DbContextが配置されるとObjectContextが破棄され、Disposeが呼び出され、ストア接続が破棄されます。
私はそれが実際に実行されていることを確認する以外にこれをテストしていません。それが本当にあなたのメモリ使用の問題に役立つかどうかを知ることは非常に興味深いでしょう。
トラッキング対ノートラッキングの効果を見ましたか?それとも、常にトラッキングが必要ですか? –
私たちは決して追跡する必要はありませんが、それがオンであるかどうかには違いはありません。とにかくGCを実行すると、そのような記憶を整理すべきだと思います。 – jlew