I'm using MEF as the IoC container in WPF with Caliburn.Micro framework. The MEF container resides in the Bootstrapper. Bootstrapper has the method:
protected override void OnStartup(object sender, StartupEventArgs e)
{
DisplayRootViewFor<ViewModels.Main.MainViewModel>();
}
Now, the MainViewModel has this:
private IEnumerable<ExportFactory<Screen>> _screenList { get; set; }
[ImportingConstructor]
public MainViewModel(IEventAggregator eventAggregator, [ImportMany] IEnumerable<ExportFactory<Screen>> screenList)
{
_screenList = screenList;
eventAggregator = eventAggregator;
_eventAggregator.Subscribe(this);
}
The class basically has an IEnumerable of ExportFactory. A Screen is basically a ViewModel that inherits from VMBase which in turn inherits from Screen. Now, some of those ViewModel use a Unit of Work, which, in turn, has a DbContext injected into it via the constructor.
So basically, the dependency chain is like this:
DbContext -> UnitOfWork (IDisposable) -> ViewModelBase(IDisposable) -> ViewModels.
These ViewModel are instantiated using the ExportFactory in the MainViewModel.
The MainViewModel is subscribed to the eventAggregator, and Handler of MainViewModel calls the ExportFactory to create a new instance of a ViewModel as necessary. The problem is, when that ViewModel is closed, the DbContext is not properly disposed of.
This is the Handle method:
public void Handle(Type message)
{
DeactivateItem(ActiveItem, true);
ActivateItem(screenList.FirstOrDefault(c => c.CreateExport().Value.GetType() == message).CreateExport().Value);
}
This creates new instances of DbContext, but doesn't call Dispose() of ViewModelBase ever, as I verified using breakpoints.
How can I properly dispose of the DbContext in my application?
What I have tried:
I tried changing the Handle method to call Dispose() like this:
DeactivateItem(ActiveItem, true);
_currentLifetimeContext?.Dispose();
_currentLifetimeContext = _screenList.FirstOrDefault(c => c.CreateExport().Value.GetType() == message).CreateExport();
ActivateItem(_currentLifetimeContext.Value);
but it throws an error "The operation cannot be completed because the DbContext has been disposed." the second time I try to create a ViewModel using the ExportFactory.
Once the DbContext has been disposed, the ExportFactory cannot create any instance of ViewModel that has the DbContext injected into its constructor anymore.
I want to dispose the DbContext every time a ViewModel is closed, and when a new ViewModel is activated, create a new instance of DbContext and inject it to the ViewModel as necessary.