在EntityFramework中刷新数据

时间:2016-06-21 12:59:41

标签: c# wpf entity-framework structuremap unit-of-work

我编写了一个WPF应用程序,但是我在刷新数据时遇到了问题,这些数据是从SQL Server数据库中提取的。

我使用StructureMap来注入依赖项,还管理DBContext的生命周期。这是我的StructureMap配置:

ObjectFactory.Container.Configure(cfg =>
{
   cfg.For<IUnitOfWork>()
      .LifecycleIs(new ThreadLocalStorageLifecycle())
      .Use<DBContext>();
});

但是当我从另一个应用程序实例或直接从SQL Server编辑记录时,之前获取过该记录的客户端无法自行刷新并只显示未修改的数据。

我使用 .LifecycleIs(new ThreadLocalStorageLifecycle())在每个线程上使用不同的Context来清除EntityFramework的缓存,但它不起作用。

这是我的服务类:

public class DraftService : IDraftService
{
    IUnitOfWork _uow;
    IDbSet<Models.Draft> _draft;

    public DraftService(IUnitOfWork uow)
    {
        _uow = uow;
        _draft = _uow.Set<Models.Draft>();
    }

    public Models.Draft GetByID(long id)
    {
       return _draft.Find(id);
    }
}

我使用的服务如下:

public class Draft
{
    private IUnitOfWork _uow;
    private IDraftService _draftService;

    public Draft(IUnitOfWork uow, IDraftService draftService)
    {
        _uow = uow;
        _draftService = draftService;
    }

    public async Task<Models.Draft> GetByID(long id)
    {
        return await Task.Run(() => _draftService.GetByID(id));
    }
}

有什么问题?为什么它不刷新数据?

提前致谢。

2 个答案:

答案 0 :(得分:2)

我认为结构图不是您的问题,您在跟踪实体时遇到问题。看一下这篇文章:http://www.entityframeworktutorial.net/change-tracking-in-entity-framework.aspx

这可能是通过以下代码解决的:

Models.Draft query = _draft.AsNoTracking().FirstOrDefault(r=>r.ID == id);

我希望它有所帮助。

实体框架中的更改跟踪 本节介绍实体框架如何跟踪实体的变化。

答案 1 :(得分:1)

编辑:经过一段时间的清醒,这就是发生的事情。

替换:return _draft.Find(id); // Find use the Cache if it can. 通过:return _draft.SingleOrDefault(x => x.id == id) // SingleOrDefault should Fetch from the database each time.

我的评论不够明确让我们来看看:

public class DraftService : IDraftService
{
IUnitOfWork _uow; <-- if this is disposed and _draft is accessed you'll get an error.
IDbSet<Models.Draft> _draft; <-- might be cached.

public DraftService(IUnitOfWork uow)
{
    _uow = uow; <--- this context is always the same
    _draft = _uow.Set<Models.Draft>();
}

public Models.Draft GetByID(long id)
{
   return _draft.Find(id); <---- this will always use the cached context.
}
}

如果你让它看起来像这样。 你得到的问题要少得多。

public class DraftService : IDraftService
{
Container _ctn;

public DraftService(Container ctn)
{
    _ctn= ctn;
}

public Models.Draft GetByID(long id)
{
   using(var uow = _ctn.Resolve<IUnitOfWork>()){ // new fresh context. don't forget the AlwaysUnique.
   return uow.Set<Draft>().Find(id); // should return the newer revision.
}}
}

如果您不想传递容器:

    public class DraftService : IDraftService
{
IUnitOfWorkResolver _rslv;

public DraftService(IUnitOfWorkResolver rslv)
{
    _rslv= rslv;
}

public Models.Draft GetByID(long id)
{
   using(var uow = rslv.GetContext()){ // new fresh context. don't forget the AlwaysUnique.
   return uow.Set<Draft>().Find(id); // should return the newer revision.
}}
}


public class UnitOfWorkResolver{
   public IUnitOfWork GetContext(){
     return new DBContext(); //or whatever you want you could use Container.Resolve<IUnitOFWork>() instead.
   }
}

我没有放入IUnitOfWorkResolver,但你明白了......