I'm using EFCore to load a 'User' entity and the related 'Orders' the user made.
I have a constructor (simplified example from the real code) which loads the user with id=1 and implements a command to update the changes in LoadedUser entity. But the CmdApply is clearly wrong in the current code:
public User LoadedUser { get; set; }
public MyViewModel
{
LoadedUser = loadUser(1);
CmdApply = new ActionCommand(p =>
{
using (var db = new MyDbContext())
{
try
{
// Save changes into database
db.SaveChanges();
}
catch (Exception e)
{
UiTools.StatusBar.AddNotification($"Failed to update user in database: {e.InnerException.Message}");
}
}, p => true)); // TODO Instead 'true' check for changes in LoadedUser
}
The loadUser() method goes like:
private User loadUser(int id)
{
using (var db = new MyDbContext())
{
// Load the user completely with all its navigation properties
var loadedUser = db.Users
.Include(s => s.Orders)
.SingleOrDefault(s => s.Id == id);
return loadedUser;
}
}
So, after loadUser() is called in the constructor, MyDbContext is disposed as the using block is left. Now, when the CmdApply is invoked the user wouldn't be saved as it is detached from the DbContext because of the short lifetime of the DbContext caused by the using blocks.
Sure, I could create the DbContext in the constructor and then it would be alive as long as the view model is alive. But as I read in the documentation, DbContexts should be alive for as short a time as possible. How can such a situation be handled?