EF返回旧值 [英] EF returns old values

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

问题描述

我在桌面应用程序中将EF6 + WPF与MVVM设计模式一起使用.我也将Autofac用作DI容器.

I'm using EF6 + WPF with MVVM design pattern in my desktop application. I'm using also Autofac as DI container.

我了解了很多有关EF上下文生命周期管理的知识,并且决定只对单个视图模型实例使用EF上下文的一个实例.我发现了有关该方法的几篇有趣的文章,因此我认为这是管理EF上下文的唯一好方法.我使用Autofac来管理EF生命周期,因此每次创建新的视图模型时,只会创建一个新的EF上下文.

I read a lot about EF context lifetime management and I decided to have only one instane of EF context for single view model instance. I found several interesting articles about that approach, so I thought that it is only good way to manage EF context. I use Autofac to manage EF lifetime, so every time I create new view model, there will be created only one new EF context.

但是,当然,我遇到了一个问题.我的大多数EF查询工作正常,但以下查询始终返回旧的(缓存的)值.每次我按执行"按钮时都会调用此查询,因此每个视图/视图模型有很多执行

But of course, I came across a problem. Most of my EF queries work good, but the following query always returns old (cached) value. I call this query every time I push 'Execute' button, so there are many executions per single view / view model

this.context.someTable.Where(arg => arg.value == "value").Single();

我知道我总是可以使用以下代码重新加载实体

I know that I can always reload the entity with following code

this.context.Entry(entity).Reload();

但是对我来说,这不是一个好的解决方案.我也知道,如果我处理当前上下文并在下一个查询之前重新创建,我将始终收到当前值.但是,这种方法与每个视图模型方法的一个上下文冲突.

But for me it is not a good solution. I know also that if I dispose current context and recreate before next query I will always receive current values. But this approach conflicts with one context per one view model approach.

为了避免EF缓存问题并仍然具有良好的性能,我应该解决/更改什么.

What should I fix / change to avoid EF caching issues and still have good performance.

推荐答案

您不应该保留上下文

我建议您放弃单个共享上下文.我最近是针对大型WPF应用程序执行此操作的. EF上下文被设计为工作单元,应使用它,然后调用.Dispose().如果需要热切阅读关系属性,则应使用.Include()提示.您应该在using块中构造上下文,以便知道失去作用域的位置,并确保上下文被处置.

I would recommend you abandon the single shared context. I did this recently for a large WPF application. An EF context is designed to be a unit-of-work, you should use it and then call .Dispose(). If you need to read in relationship properties eagerly, you should use .Include() hints. You should construct your contexts in a using block so you know where you lose scope, and to ensure the context is disposed.

您将发现EF的性能实际上可能会下降,因为它需要引用其内部缓存和状态.我发现如果使用共享上下文,则批量数据插入模式会恶化. EF的性能不如RDBMS好.

You will find that performance of EF can actually diminish as it needs to refer to its internal cache and state. I have found bulk data insert patterns deteriorate if a shared context is used. EF doesn't perform as well as an RDBMS.

正如您所经历的那样,您可以持久保留上下文并从缓存的实体中受益,但是如果这变得很痛苦,由于系统的性质和用户的要求,那么您就不再真正从缓存中受益.您支持的RDBMS应该足够快.一旦以任何方式进行缓存(包括EF二级缓存和ASP.NET输出缓存),就立即需要计划如何使缓存的实体过期.这为您的编码人员增加了很多工作,并为您的系统提供了引人注目的新的失败方法.

As you have experienced, you can persist the context and benefit from cached entities, but if that's becoming a pain, due to the nature of your system and requirements of the user, you are not really benefiting from the caching anymore. Your backing RDBMS should be fast enough. As soon as you cache in any way (including EF second-level caching and ASP.NET Output Caching), you immediately need to plan how to expire your cached entities. This adds a lot more work for your coders, and gives your systems spectacular new ways to fail.

例如,考虑到EF的好处是关系属性的自动解决.您可以无缝地遍历数据图,直到您找到一个已缓存且过时的实体.在这种情况下,很难在检索此类实体之前使缓存过期.

For instance, consider that a benefit of EF is the automatic resolution of relationship properties. You can be seamlessly reaching across a graph of data until you hit an entity which is cached and stale. In such circumstances, it is difficult to expire the cache before retrieving such entities.

但是如果您必须在Update上重新加载

如果您真的不想将架构更改为Microsoft推荐/计划的方式.我建议您跟踪所有打开的上下文(在构造时添加到静态集合中,在处置时删除,使用finalizer模式进行双重检查,并在处置时抑制finalizer),并在保存管道中实现一些通用代码(有几种方法)这样)会尝试在所有打开的上下文中重新加载实体.这是使EF实体缓存过期的一种主动方式.这可能会影响较大集合上的性能,但是您可能需要处理实体白名单或黑名单,而不是处理所有已保存的实体.

If you really don't want to change your architecture to the Microsoft recommended/intended way. I suggest you keep track of all open contexts (adding to static collection on construction, removing on dispose, double-check with finalizer pattern, and finalizer suppression on dispose), and implement some generic code in the save pipeline (there are a few ways of doing this) which attempts to reload the entity across all open contexts. This is an proactive way of expiring your EF entity caches. This may affect performance on larger collections, but you could have a whitelist or blacklist of entities to process, rather than processing all saved entities.

我个人感到很高兴,我进行了更改(将结构更改为短期环境),从长远来看,在代码可维护性和系统稳定性方面有巨大的好处.

Personally, I'm glad I made the change (restructuring to short-lived contexts), long term there are huge benefits in terms of code maintainability and system stability.

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

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