C# 使用多实体框架上下文快速修复ViewModel
目前正在使用MVVM模式处理MVC应用程序。它最初是这样编写的,所有ViewModels都继承自同一BaseViewModel,后者构建了一个实体框架存储库,如下所示:C# 使用多实体框架上下文快速修复ViewModel,c#,wpf,entity-framework,mvvm,C#,Wpf,Entity Framework,Mvvm,目前正在使用MVVM模式处理MVC应用程序。它最初是这样编写的,所有ViewModels都继承自同一BaseViewModel,后者构建了一个实体框架存储库,如下所示: public abstract class BaseViewModel : INotifyPropertyChanged { private static MyRepository _rep; protected static MyRepository rep { get
public abstract class BaseViewModel : INotifyPropertyChanged
{
private static MyRepository _rep;
protected static MyRepository rep
{
get
{
if (_rep == null)
_rep = new MyRepository();
return _rep;
}
}
}
我继承的应用程序实际上没有单元测试,因此我决定进行一些重构,使其更易于测试。因此,我在存储库上放置了一个接口,并为每个viewmodel提供了自己的副本,以便对其进行模拟以进行测试:
public class MyViewModel : BaseViewModel
{
private IMyRepository _rep;
public AvailabilityHistoryViewModel()
: this(new MyRepository())
{ }
public MyViewModel(IMyRepository rep)
{
_rep = rep;
DoStuff();
}
}
大多数情况下,这是可以接受的。但后来我遇到了一个以前的功能按钮,它突然导致应用程序崩溃,出现了可怕的“entity object不能被IEntityChangeTracker的多个实例引用”错误
事实证明,应用程序中有一个UserControl,它在多个地方使用,它也继承自BaseViewModel,因此有自己的存储库副本
public abstract class BaseTreeViewItem : BaseViewModel
{ }
当在父viewmodel中使用它,并传递其属性时,很可能最终会生成一个EF对象,该对象是通过UserControl存储库创建的,并传递给viewmodel并与其存储库一起保存的,因为它们是不同的上下文,所以会导致崩溃
简单的解决方法就是退出我的更改,让使用此UserControl的ViewModels返回到使用BaseViewModel存储库。但这很难看。对此进行适当的修复,重新安排内容,使UserControl没有自己的上下文,这将花费我实际得到的更长时间。还有别的办法吗?我可能会错过一些东西,但在我看来,拥有单一存储库可以解决您的问题。
您已经通过接口使用了它们,所以您可以简单地将它们注入。它会——事实上,原始模型有一个单例存储库。然而,要做到这一点并保持可测试性,我需要实现依赖注入,这本身就是一个非常复杂的过程,甚至需要使用像Ninject这样的现成软件包。或者我遗漏了一些明显的东西?是的,然后您应该实现依赖注入,这是在您的体系结构中非常好的模式。起初,这似乎是额外的工作,但它通过松散耦合提供的灵活性极大地提高了代码的可维护性和可测试性。而实现一个好的基于框架代码的框架(如Ninject)并不像看上去那么复杂。你在项目中做得越早,工作就越少。他们有非常好的教程,是的,但这是问题的一部分-现在还不早,这是一个发布的应用程序,我在加入项目之前做出了一些糟糕的架构决策。啊,好吧,这让事情变得有点复杂。尽管我仍然建议您使用DI。你现在付出的努力,以后肯定会有回报的。如果您有一个可靠的测试基础,那么您就不应该害怕“一些重构”。否则,您应该开始构建它:)