2016-11-12 7 views
1

Я использую EF6 с базой данных SQLite. Я создаю и удаляю объекты 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 на объекте соединения и никогда не отзывается от него.

Мой (очень некрасиво) обходной путь, чтобы вручную «очистить» поле StateChange события после каждого использования, как это:

conn 
    .GetType() 
    .GetField("StateChange", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance) 
    .SetValue(conn, null); 

Это известная проблема? Есть ли лучшее обходное решение?

ответ

1

У меня была та же проблема. Вызов Dispose() в EntityConnection, похоже, решает проблему.

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(); 
    } 
} 
Смежные вопросы