SQLiteデータベースでEF6を使用しています。私はそれぞれの要求に対してDBContext
のオブジェクトを作成して処分しますが、データベースはメモリにキャッシュされたままになるので、SQLiteConnection
オブジェクトをキャッシュします。このような状況では、EFがメモリをリークしているように見えます。ここでEntity Framework 6メモリリーク
は、最小限の作業のサンプルです:
class Program
{
static void Main(string[] args)
{
// use one connection for the lifetime of the application
using (var conn = new System.Data.SQLite.SQLiteConnection("Data Source=:MEMORY:"))
{
// create sample DB
conn.Open();
using (var context = new MyContext(conn, false))
context.Database.ExecuteSqlCommand("CREATE TABLE SomeTable(Id INTEGER PRIMARY KEY AUTOINCREMENT)");
while (true)
{
// access database
using (var context = new MyContext(conn, false))
{
var x = System.Linq.Enumerable.Count(context.SomeTable);
}
// show memory usage
System.Console.Write("{0:0,0} Bytes \r", System.GC.GetTotalMemory(false));
}
}
}
}
class MyContext : System.Data.Entity.DbContext
{
public MyContext(System.Data.Common.DbConnection existingConnection, bool contextOwnsConnection)
: base(existingConnection, contextOwnsConnection)
{ }
public System.Data.Entity.DbSet<SomeTableRow> SomeTable { get; set; }
}
[System.ComponentModel.DataAnnotations.Schema.Table("SomeTable")]
class SomeTableRow
{
public int Id { get; set; }
}
私はこれを実行すると、プロセスのメモリ使用量が増加し続けます。
私は、問題はSystem.Data.Entity.Core.EntityClient.EntityConnection
が接続オブジェクトのStateChange
イベントにサブスクライブし、それから決してサブスクライブしないことだと思います。
conn
.GetType()
.GetField("StateChange", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance)
.SetValue(conn, null);
これは既知の問題です:
私(非常に醜い)回避策は、このように、各使用後にStateChange
イベントフィールド手動で「クリア」にありますか?より良い回避策がありますか?