2016-11-12 51 views
1

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イベントフィールド手動で「クリア」にありますか?より良い回避策がありますか?

答えて

1

私は同じ問題を抱えていました。 EntityConnectionでDispose()を呼び出すと、問題が解決されたようです。

public class CustomDbContext : DbContext 
{ 
    private EntityConnection _entityConnection; 

    public CustomDbContext(EntityConnection connection) 
     : base(connection, false) 
    { 
     _entityConnection = connection; 
    } 

    protected override void Dispose(bool disposing) 
    { 
     base.Dispose(disposing); 
     if (disposing && _entityConnection != null) 
      _entityConnection.Dispose(); 
    } 
} 
関連する問題