c# – MVVM light应用程序 – 如何正确清理ViewModels

我正在使用
WPF中的cookbook窗口应用程序,它包含一个窗口和几个userControls,它们使用来自MVVM Light的消息与relayCommands相互替换.

该应用程序使用从entityFramework生成的数据库.除了第一次执行文件之外发生的问题是程序显示许多警告和错误,例如:

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

在ViewModelLocator中我有这个:

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>();
}

而且我用来切换userControls的消息正在创建ViewModel的新实例,例如:

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

我已经玩弄了ViewModels,使它们成为单例,以确保系统中只有单个副本,但SimpleIoc需要公共构造函数进行注册.而且我也不知道这是否会对我的问题有所帮助.另外我没有告诉你的是ViewModelLocator只在xaml中使用,所以我甚至没有它的实例来清理这些东西. (我可能使用它错了,但我不知道应该如何使用它)

问题是我不知道如何以及在何处清理所有ViewModel,因为它们在我提到的许多地方都被创建了,其中一些可能持有* .mdf文件.

最佳答案 正如评论中所提到的,你得到了

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

警告(以及在充分重试错误之后)来自构建器中编译器的消息,因为为正在运行/调试的应用程序创建了进程:

>尚未完成,或
>未关闭与数据库文件的所有连接.

因此,当您再次构建它时,其文件句柄仍然打开,您无法复制打开的文件.

很难根据您在问题中发布的代码确定这是直接原因,但这一行:

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

显然是有问题的,因为它返回一个新实例,而不是SimpleIoC容器中的单例生命周期实例.虽然从正确的DI角度来看仍然很难看,但您可以将其更改为:

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

因此,它不会创建MainViewModel的新实例,而是从IoC容器中返回一个实例.

此外,您可能希望确保在容器中注册了数据库上下文,并将其注入到需要它的视图模型中.说明这一点(假设您的数据库上下文/服务类名为MyDbContext,实现IMyDbContext,并将连接字符串作为其构造函数参数):

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

现在,您还必须确保在应用程序退出时执行适当的清理,以便在IMyDbContext实例上调用Dispose,以及应用程序中需要处理的任何其他潜在资源.如果还没有这样做,通过MVVM Light,您可以通过对应用程序上的Application.Exit Event作出反应来做到这一点:

点赞