繁体   English   中英

实体框架返回旧数据

[英]Entity Framework returning old data

我有一个问题,EF没有返回3层WPF应用程序中的最新数据,我怀疑它与我如何处理我的上下文的生命周期有关。 这是场景:

UnitOfWork中包含几个存储库。 还有一个服务(MyService),它使用UnitOfWork。 还必须直接从UI调用此UnitOfWork,而不通过服务。

在我的主窗口的ViewModel中,我创建了一个新窗口(首先使用ViewModel):

var dialog = new DialogViewModel(_eventAggregator, _unitOfWork, Container.Resolve<CarService>());

这个主窗口ViewModel有一个UnitOfWork,它已经在构造函数中注入,并传递给DialogViewModel。

CarService的构造函数也需要一个UnitOfWork,它也在它的构造函数中注入:

public CarService(IUnitOfWork unitOfWork){
    _unitOfWork = unitOfWork;
}

当在DialogViewModel中使用CarService进行查询以检索某些数据并进行一些更新时,它第一次正常工作。 但是,当下次检索该数据时进行相同的查询,而不是返回最新的修改后的数据,它将返回旧的/缓存的数据。 使用UnitOfWork(在CarService内部)的查询如下所示:

var values = _unitOfWork.GarageRepository.GetSomeValues();
_unitOfWork.GarageRepository.MakeSomeChangesToTheValuesUsingStoredProcedure();

第二次调用它时,值不包含最新版本的数据; 但它已在DB中成功更新。

我正在使用Unity进行DI,这就是我的容器的样子:

public class Container
{
     public static UnityContainer Container = new UnityContainer();

     // Called once in the AppBoostraper, as soon as the GUI application starts 
     public void BuildUp()
     {
          Container.RegisterType<IUnitOfWork, UnitOfWork>();
          Container.RegisterType<ICarService, CarService>();
     }
}

为什么不返回正确的数据,我该如何解决?

我终于找到了问题,这与我对unitOfWork / dbcontext生命周期的管理有关。

我正在加载一些实体,然后用存储过程更新它们(因此代码中的实体不再是最新版本),然后再次加载查询; 此时EF从缓存中获取值而不是从DB中获取值。

我发现了两种解决方法:

  1. 一个相当“hacky”的,迫使实体重新加载:

     Context.Entry(entity).Reload(); 
  2. 使用using封装unitOfWork使用,以便在每个事务结束时处理上下文,从而在下次获取新数据。 我认为这更符合UnitOfWork的意图,对我来说感觉更强大。 我还将UnitOfWork包装在一个工厂中,所以现在它被注入到构造函数中。

     using (var uOw = new unitOfWorkFactory.GetNew()) { // make the queries } 

默认的LifetimeManager for Unity是TransientLifetimeManager,这意味着每次解析时都会获得一个新实例(包括注入时)。 因此,考虑到您的注册,您将获得一个新的CarService,每次调用Resolve()时都会有一个UnitOfWork的新实例,并且会在主窗口ViewModel中注入一个新的不同实例。

所以你的ViewModel得到一个UoW,CarService得到一个单独的UoW,而更新一个意味着另一个现在由于缓存而过时了。

您需要做的是为具有适当范围的上下文设置LifetimeManager,或者遵循工厂。 Unity没有内置的那么多LM,但LifetimeManager类基本上是一个美化的地图(本质上有一个Set,Get和Remove方法)。

我不太了解WPF及其生命周期建议实施。 也许它可以是单例(它将在程序运行的整个时间内保持相同的上下文),也许它可以由线程的CallContext支持。

另一种选择是在通过调用Container.Resolve<CarService>(new ParameterOverride("unitOfWork", _unitOfWork))解析CarService时传递UoW实例。 这将使生命周期管理与主窗口ViewModel的生命周期保持一致。 但是,这种方法存在问题,因为您的VM类对CarService知之甚少(特别是它有一个UoW)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM