问题
I am using the dotMemoryUnit to prove the my DbContext object is getting garbage collected properly.
I feel that this code should work properly in a unit test, but the test always fails. The only thing I can guess is EF Core is holding a reference somewhere.
Edit: I'm not sure the suggested question addresses this problem as this is .Net Core and not .Net Framework. The documentation for GC.Collect()'s default is forced and the documentation says nothing about hints.
Edit 2: I did find the answer below.
Thoughts?
public class UnitTest1
{
public UnitTest1(ITestOutputHelper output)
{
DotMemoryUnitTestOutput.SetOutputMethod(output.WriteLine);
}
[Fact]
[DotMemoryUnit(FailIfRunWithoutSupport = false)]
public void DummyContext_DisposesContextOnGarbageCollect()
{
// Arrange
var options = new DbContextOptionsBuilder<DummyContext>()
.UseSqlServer("data source=ASqlServer;Integrated Security=true");
using (var ctx = new DummyContext(options.Options))
{
// do nothing
}
GC.Collect();
GC.WaitForPendingFinalizers();
dotMemory.Check(
memory =>
Assert.Equal(
0,
memory.GetObjects(where => where.Type.Is<DummyContext>()).ObjectsCount));
}
private class DummyContext : DbContext
{
public DummyContext(DbContextOptions options)
: base(options)
{
}
}
}
回答1:
After a little more research, I have found the answer in this post from Jet Brains:
Since all of our logic is being run in one method (our test method), the garbage collector will not clean up local variables that are still available in the context of our function.
The post suggests wrapping the code in an action method.
For others that may have this problem, below is my new test method:
[Fact]
[DotMemoryUnit(FailIfRunWithoutSupport = false)]
public void DummyContext_DisposesContextOnGarbageCollect()
{
var isolator = new Action(
() =>
{
// Arrange
var options = new DbContextOptionsBuilder<DummyContext>()
.UseSqlServer("data source=ASqlServer;Integrated Security=true");
using (var ctx = new DummyContext(options.Options))
{
// do nothing
}
});
isolator();
GC.Collect();
GC.WaitForPendingFinalizers();
SetProcessWorkingSetSize(System.Diagnostics.Process.GetCurrentProcess().Handle, -1, -1);
dotMemory.Check(
memory =>
Assert.Equal(
0,
memory.GetObjects(where => where.Type.Is<DummyContext>()).ObjectsCount));
}
来源:https://stackoverflow.com/questions/59570078/why-ef-core-2-2-6-does-not-garbage-collect