views:

93

answers:

1

Hi,

Here's a test:

WeakReference ref1;
WeakReference ref2;

TestRepositoryEntitiesContainer context;
int i = 0;
using (context = GetContext<TestRepositoryEntitiesContainer>())
{
    context.ObjectMaterialized += (o, s) => i++;
    var item = context.SomeEntities.Where(e => e.SomePropertyToLookupOn == "some property").First();
    context.Detach(item);
    ref1 = new WeakReference(item);
    var newItem = new SomeEntity {SomePropertyToLookupOn = "another value"};
    context.SomeEntities.AddObject(newItem);
    ref2 = new WeakReference(newItem);
    context.SaveChanges();
    context.SomeEntities.Detach(newItem);

    newItem = null;
    item = null;    
}
context = null;

GC.Collect();
Assert.IsFalse(ref1.IsAlive);
Assert.IsFalse(ref2.IsAlive);

First assert passes, second fails... I hope I'm missing something, it is late... But it appears that detaching a fetched item will actually release all handles on the object letting it be collected. However, for new objects something keeps a pointer and creates a memory leak.

NB - this is EF 4.0

Anyone seen this before and worked around it?

Thanks for your help!

Tom

+1  A: 

Did you try running this with optimizations (i.e. Release mode) and without a debugger attached? The JIT compiler may be artificially extending the lifetime of the newItem object until the end of the method.

I was able to reproduce the issue when running without optimizations, but not with optimizations.

David DeWinter