Using MVVM light - how to properly clear ViewModels

I am working on a cookbook application window in WPF consisting of a single window and several user controllers that replace each other using relay commands using messages from MVVM Light.

The application works with a database that is generated from entityFramework. The problem that occurs after the first but first execution of the file is that the program shows many errors and errors, such as this:

Warning 1 Could not copy "...\cookbook\Cookbook.Services\Database1.mdf" to "bin\Debug\Database1.mdf". Beginning retry 1 in 1000ms. The process cannot access the file '...\cookbook\Cookbook.Services\Database1.mdf' because it is being used by another process. Cookbook.Services 

In ViewModelLocator, I have this:

 public ViewModelLocator() { ServiceLocator.SetLocatorProvider(() => SimpleIoc.Default); SimpleIoc.Default.Register<MainWindowViewModel>(); SimpleIoc.Default.Register<MainViewModel>(); SimpleIoc.Default.Register<FoodTypeViewModel>(); SimpleIoc.Default.Register<ShoppingCartViewModel>(); SimpleIoc.Default.Register<MenuViewModel>(); SimpleIoc.Default.Register<MenuListViewModel>(); SimpleIoc.Default.Register<MenuCalendarViewModel>(); SimpleIoc.Default.Register<ChooseFoodWindowViewModel>(); } 

And also the messages I use to switch userControls create new instances of ViewModels, such as:

  BackToMainCommand = new RelayCommand(() => { Messenger.Default.Send<ViewModelBase>(new MainViewModel()); }, () => true); 

I played with ViewModels to make them singleton, to make sure that the system has only single copies, but SimpleIoc needs public constructors to register. And also I do not know if this will help my problem. Also, I did not tell you that ViewModelLocator is used only in xaml, so I do not even have my own instance for cleaning the material. (Maybe I'm wrong, but I don’t know how to use it)

The problem is that I don’t know how and where to clear all ViewModels, as they look in many places that I mentioned, and some of them probably contain a * .mdf file.

+5
source share
2 answers

As mentioned in the comments, you get

Warning 1 Failed to copy "... \ cookbook \ Cookbook.Services \ Database1.mdf" to "bin \ Debug \ Database1.mdf". Start repetition 1 in 1000 ms.

The process cannot access the file '... \ cookbook \ Cookbook.Services \ Database1.mdf' because it is being used by another process. Cookbook.Services

warning (and after reporting a sufficient number of attempts) from the compiler in the assembly, because the process created for the application that you ran / debugged:

  • not yet completed, or
  • all connections to the database file are not closed.

So, when you create it again, its file descriptor is still open, and you cannot copy it through an open file.

It is hard to establish from the code that you posted in your question what the direct reason for this is, but this line:

 Messenger.Default.Send<ViewModelBase>(new MainViewModel()); 

clearly problematic because it returns a new instance instead of a singleton lifecycle instance from the SimpleIoC container. Although still ugly in terms of DI, you can change it to:

 Messenger.Default.Send<ViewModelBase>(ServiceLocator.Current.GetInstance<MainViewModel>()); 

Therefore, it will not create a new instance of your MainViewModel , but will return it from the IoC container.

In addition, you may want to make sure that your database context is registered in your container and entered into the desired view models. Illustrating this (if your database context / class is called MyDbContext , implements IMyDbContext and takes the connection string as a constructor argument):

 SimpleIoc.Default.Register<IMyDbContext>(() => new MyDbContext(GetMyConnectionString())); 

Now you also need to make sure that the correct cleanup is performed when you exit the application, so that Dispose is called on the IMyDbContext instance and any other potential resources of your application that require removal. If this has not already been done, through MVVM Light you can do this by responding to the Application.Exit event on Application :

+2
source

Your problem is probably caused by how you use your DbContext. You did not present in your question how you are doing, so I will try to guess what is happening on your side. You should always make sure that after using DbContext you will destroy it immediately. It should not be stored throughout the life of the application. I do not see that you are registering it using IoC, so I assume that you are just creating it somewhere in your ViewModels. In this case, you should always have DbContext objects in use () to ensure that they are located. If you are full, that of course you should not open any connection for your db when you close the application in the usual way.

Another case involves debugging your application in VS. This is done by default with VS hosting, so when you click the "stop debugging" button, DbContexts with open connections is not deleted, and the VS hosting process is not killed. To avoid such situations, I would recommend that you disable the VS VS process. You can set it in the project properties β†’ Debugging β†’ and uncheck the Enable Visual Studio hosting process box. However, this may decrease slightly when your application starts to work when debugging it.

0
source

All Articles