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

查看:33
本文介绍了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.

但是如果您必须在更新时重新加载

如果您真的不想将架构更改为 Microsoft 推荐/预期的方式.我建议您跟踪所有打开的上下文(在构造时添加到静态集合,在处置时删除,使用终结器模式仔细检查,并在处置时抑制终结器),并在保存管道中实现一些通用代码(有几种方法)这样做)它试图在所有打开的上下文中重新加载实体.这是一种使 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天全站免登陆