C# MVVM灯光应用程序-如何正确清理ViewModels
我正在WPF中开发一个cookbook窗口应用程序,它由一个窗口和几个用户控件组成,这些控件使用MVVM Light中的消息用relayCommand相互替换 应用程序使用从entityFramework生成的DB。除第一次执行文件外,所有文件执行后出现的问题是程序显示了许多警告和错误,例如:C# MVVM灯光应用程序-如何正确清理ViewModels,c#,wpf,entity-framework,mvvm,viewmodellocator,C#,Wpf,Entity Framework,Mvvm,Viewmodellocator,我正在WPF中开发一个cookbook窗口应用程序,它由一个窗口和几个用户控件组成,这些控件使用MVVM Light中的消息用relayCommand相互替换 应用程序使用从entityFramework生成的DB。除第一次执行文件外,所有文件执行后出现的问题是程序显示了许多警告和错误,例如: Warning 1 Could not copy "...\cookbook\Cookbook.Services\Database1.mdf" to "bin\Debug\Database1.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
在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>();
}
公共ViewModelLocator()
{
ServiceLocator.SetLocatorProvider(()=>SimpleIoc.Default);
SimpleIoc.Default.Register();
SimpleIoc.Default.Register();
SimpleIoc.Default.Register();
SimpleIoc.Default.Register();
SimpleIoc.Default.Register();
SimpleIoc.Default.Register();
SimpleIoc.Default.Register();
SimpleIoc.Default.Register();
}
此外,我用来切换用户控件的消息正在创建ViewModels的新实例,例如:
BackToMainCommand = new RelayCommand(() =>
{
Messenger.Default.Send<ViewModelBase>(new MainViewModel());
},
() => true);
BackToMainCommand=newrelaycommand(()=>
{
Send(新的MainViewModel());
},
()=>正确);
我已经玩弄了ViewModels,使它们成为单副本,以确保系统中只有单副本,但SimpleIoc需要公共构造函数进行注册。而且我也不知道这是否对我的问题有帮助。我没有告诉你的是ViewModelLocator只在xaml中使用,所以我甚至没有它的实例来清理这些东西。(我可能用错了,但我不知道该怎么用)
问题是,我不知道如何以及在何处清理所有ViewModel,因为它们是在我提到的许多地方创建的,其中一些可能保存着*.mdf文件。如评论中所述,您得到的是 警告1无法将“..\cookbook\cookbook.Services\Database1.mdf”复制到“bin\Debug\Database1.mdf”。开始在1000毫秒内重试1次 进程无法访问文件“…\cookbook\cookbook.Services\Database1.mdf”,因为另一个进程正在使用该文件。烹饪书,服务 生成中来自编译器的警告(以及在足够重试错误后)消息,因为为正在运行/调试的应用程序创建的进程:
Messenger.Default.Send<ViewModelBase>(new MainViewModel());
因此,它不会创建MainViewModel
的新实例,而是从IoC容器中返回一个实例
此外,您可能希望确保在容器中注册了数据库上下文,并将其注入到需要它的视图模型中。对此进行了说明(假设数据库上下文/服务类名为MyDbContext
,实现了IMyDbContext
,并将连接字符串作为其构造函数参数):
SimpleIoc.Default.Register(()=>newmydbcontext(GetMyConnectionString());
现在,您还必须确保在应用程序退出时执行适当的清理,以便对
IMyDbContext
实例和应用程序中需要处理的任何其他潜在资源调用Dispose
。如果还没有做到这一点,通过MVVM Light,您可以通过对应用程序上的
:做出反应来做到这一点。您的问题可能是由于您使用DbContext的方式造成的。你没有在你的问题中提出你是如何处理的,所以我将试着猜测你那边发生了什么。您应该始终确保在使用DbContext之后立即处理它。它不应在整个应用程序使用期间保存。我看不出您正在向IoC注册它,所以我假设您只是在ViewModels中的某个地方实例化了它。在这种情况下,您应该始终将DbContext对象放在using()中,以确保它们已被释放。如果您愿意,当您以普通方式关闭应用程序时,您肯定不应该打开任何与数据库的连接
另一种情况是连接到VS中调试应用程序。默认情况下,VS宿主进程会完成调试,因此当您点击“停止调试”按钮时,不会释放已打开连接的DBContext,也不会终止VS宿主进程。为了避免这种情况,我建议您尝试禁用VS托管进程。您可以在项目属性->调试->中设置它,然后取消选中启用VisualStudio宿主进程。但是,这可能会减少调试应用程序时应用程序开始运行的时间。为正在运行/调试的应用程序创建的进程(1)尚未完成,或(2)未关闭与数据库文件的所有连接。因此,如果您再次构建它,它的文件句柄仍处于打开状态,您无法复制打开的文件。请注意,调试时,特别是使用“停止调试”按钮停止调试会话时,调试进程不会直接终止。退出VisualStudio并重新启动通常可以解决这个问题。好的,这些连接在一些使用DB服务的ViewModels中。我认为那些视图模型超出了定位器或消息的范围(如果我没有错的话)。我知道重新启动VisualStudio可以解决这个问题,但我需要修复它,这样即使我使用退出按钮或窗口中的十字退出应用程序,我也可以让应用程序正常工作。
Messenger.Default.Send<ViewModelBase>(ServiceLocator.Current.GetInstance<MainViewModel>());
SimpleIoc.Default.Register<IMyDbContext>(() => new MyDbContext(GetMyConnectionString()));