给定,例如:
IEnumerable<LargeObject> Read(int x) {
// Implicit IQueryable<LargeObject> -> IEnumerable<LargeObject>
return ef6Context.LargeObjects.Where(o => o.ObjectType == x);
}
var largeObjects = Read(21281); // Returns "many" objects
// Only use/iteration of IEnumerable result
foreach (var o in largeObject) {
// When processing the second item (and so on),
// can the first (previous) "o" object be GC'ed?
Process(o);
}
是在上面处理的"大对象" 有资格的垃圾回收吗?
答案应涵盖任何内部EF缓存。
实体框架将所有实体都从数据库中检索到上下文中,以便在迭代后不会收集它们。这样做是为了跟踪更改。您可以通过在执行前在查询(文档)之前在查询上调用AsNoTracking
来禁用此功能。这样做SaveChanges
不会持续对这些实体进行任何更改。
关于天气问题,每次迭代后都会释放对象,答案是肯定的。我创建了一个简单的演示,可以通过在构造函数和Destructor中添加记录代码并添加明确的GC调用来对此进行质量。每次迭代后都会调用破坏者。
public class Program
{
public static void Main(string[] args)
{
using (var db = new MyContext())
{
//for (int i = 0; i < 1000; i++)
//{
// db.Enta.Add(new Entity());
//}
//db.SaveChanges();
foreach (var e in db.Enta.AsNoTracking())
{
Console.WriteLine(e.Id);
GC.Collect();
}
GC.Collect();
}
}
}
public class Entity
{
public Entity()
{
Console.WriteLine("ctor");
}
~Entity()
{
Console.WriteLine("destructor");
}
public int Id { get; set; }
}
public class MyContext : DbContext
{
public DbSet<Entity> Enta { get; set; }
}