实体框架返回旧数据 [英] Entity Framework returning old data

查看:129
本文介绍了实体框架返回旧数据的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



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



在我的主窗口的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();

//在AppBoostraper中调用一次,一旦GUI应用程序启动
public void BuildUp()
{
Container.RegisterType< IUnitOfWork,UnitOfWork> );
Container.RegisterType< ICarService,CarService>();
}
}

为什么没有正确的数据被返回,我如何解决它?

解决方案

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



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



我发现了两种修复方法:


  1. 相当黑客,迫使实体重新加载:

      Context.Entry(实体).Reload(); 


  2. 使用using来封装unitOfWork使用,以便上下文在每次交易,从而得到新的数据下一次。我认为这更符合UnitOfWork的意义,对我而言更为强大。我也在工厂中包装了UnitOfWork,所以现在注入到构造函数中。

      using(var uOw = new unitOfWorkFactory.GetNew())
    {
    //查询
    }



I have a problem with EF not returning the newest data in a 3 layered WPF application, and I suspect it has something to do with how I handle the lifetime of my context. This is the scenario:

There are several repositories wrapped inside a UnitOfWork. There is also one service (MyService), which uses the UnitOfWork. This UnitOfWork must also be called from the UI directly, without passing through a service.

In the ViewModel of my main window at some point I create a new window (using ViewModel first):

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

This main window ViewModel has a UnitOfWork, which has been injected in the constructor, and that is passed to the DialogViewModel.

CarService's constructor also needs a UnitOfWork, which is also injected in its constructor:

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

When CarService is used in DialogViewModel to make a query to retrieve some data and make some updates, it works fine the first time. However, when the same query is made the next time to retrieve that data, instead of returning the newest modified one it returns the old/cached one. The query using UnitOfWork (inside CarService) looks like this:

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

The second time this is called, values doesn't contain the newest version of the data; however it has been updated successfully in the DB.

I'm doing DI using Unity, and this is how my container looks like:

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

Why isn't the right data being returned, and how can I fix it?

解决方案

I finally found the problem, which had to do with my management of the unitOfWork/dbcontext lifecycle.

I was loading some entities, then updating them with a stored procedure (so the entities in the code were not up to date anymore), and then loading the queries again; at this point EF was getting the values from the cache rather than from the DB.

I found two ways of fixing this:

  1. A rather "hacky" one, force the entities to reload:

    Context.Entry(entity).Reload();
    

  2. Encapsulate the unitOfWork usage with a using, so that the context is disposed at the end of each transaction and thus getting fresh data the next time. I think this is more in line with what the UnitOfWork is meant for and feels more robust to me. I've also wrapped the UnitOfWork in a factory, so now that gets injected in the constructors.

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

这篇关于实体框架返回旧数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆