我使用带有SQLite数据库的EF6。我为每个请求创建并释放DBContext对象,但是希望缓存SQLiteConnection对象,这样数据库就会一直缓存在内存中。在这种情况下,EF似乎会泄漏内存。
下面是一个最小的工作示例:
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订阅了connection对象上的StateChange事件,并且从不取消订阅。
我的(非常难看的)解决方法是在每次使用后手动“清除”StateChange事件字段,如下所示:
conn
.GetType()
.GetField("StateChange", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance)
.SetValue(conn, null);这是一个已知的问题吗?有没有更好的变通办法?
发布于 2017-06-06 22:24:18
我也有同样的问题。在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();
}
}https://stackoverflow.com/questions/40563233
复制相似问题