EF6为何会为部分DbSet分配内存?
问题:DbContext释放后部分DbSet仍存活在堆内存中?
我有一个简单的DbContext,包含三个DbSet。用Windbg执行!dumpheap -type live查看存活对象时,发现部分DbSet还留在堆内存里。
实体类代码:
public class Delivery { public long Id { get; set; } public string Name { get; set; } public string Description { get; set; } } public class Product { public long Id { get; set; } public string Name { get; set; } } public class Category { public long Id { get; set; } public string Name { get; set; } }
DbContext代码:
internal class TestContext : DbContext { public TestContext() : base("db") { } public DbSet<Delivery> DeliveryMethods { get; set; } public DbSet<Product> Products { get; set; } public DbSet<Category> Categories { get; set; } }
Main方法:
static void Main(string[] args) { using (var db = new TestContext()) { } Console.WriteLine("done"); Console.ReadKey(); }
原因分析
EF内部元数据缓存机制:EF在初始化DbContext时,会预先加载并缓存实体模型的元数据(比如实体属性、映射规则)。为了构建这些元数据,EF可能会提前实例化部分DbSet对象,这些对象会被EF的全局元数据缓存持有,不会随DbContext的
Dispose立即被回收。这是EF的正常优化策略,用于提升后续操作的性能。垃圾回收未触发:
using块仅将DbContext标记为可回收对象,但.NET的垃圾回收器不会立即执行回收。当程序停在Console.ReadKey()时,GC还没运行,那些DbSet对象自然还留在堆内存中。你可以在using块结束后手动调用GC.Collect(); GC.WaitForPendingFinalizers();,再用Windbg检查,就能看到这些对象被回收了。延迟初始化的副作用:虽然DbSet是延迟初始化属性,但EF内部在构建模型时,可能会主动访问部分DbSet属性来完成元数据收集,导致这些DbSet被实例化并被内部引用,从而延长了它们的生命周期。
内容的提问来源于stack exchange,提问作者mahmood
相关产品推荐
相关产品推荐

