我在桌面应用程序中使用EF6 + WPF和MVVM设计模式。我也使用Autofac作为DI容器。
我读了很多关于EF上下文生命周期管理的文章,并且决定对于单个视图模型实例只有一个EF上下文的实例化。我发现了几篇关于这种方法的有趣文章,所以我认为它只是管理EF上下文的好方法。我使用Autofac来管理EF生命周期,所以每次创建新的视图模型时,都只会创建一个新的EF上下文。
但当然,我遇到了一个问题。我的大多数EF查询工作良好,但下面的查询总是返回旧(缓存)值。每次按“Execute”按钮时,我都会调用这个查询,因此每个视图/视图模型都有很多执行情况。
this.context.someTable.Where(arg => arg.value == "value").Single();我知道我总是可以用以下代码重新加载实体
this.context.Entry(entity).Reload();但对我来说,这不是一个好的解决办法。我还知道,如果我在下一个查询之前释放当前上下文并重新创建,我将始终接收当前值。但是这种方法与一个视图模型方法中的一个上下文相冲突。
我应该修复/更改什么,以避免EF缓存问题,但仍然有良好的性能。
发布于 2015-01-23 03:11:11
您不应该持久化上下文
我建议您放弃单一的共享上下文。我最近为一个大型的WPF应用程序做了这个工作。EF上下文设计为工作单元,您应该使用它,然后调用.Dispose()。如果您需要急切地阅读关系属性,则应该使用.Include()提示。您应该在using块中构造上下文,以便知道丢失范围的位置,并确保上下文被释放。
您会发现EF的性能实际上会下降,因为它需要引用它的内部缓存和状态。我发现,如果使用共享上下文,则批量数据插入模式会恶化。EF的性能不如RDBMS。
正如您所经历的,您可以持久化上下文并从缓存实体中受益,但是如果这正在成为一种痛苦,因为您的系统的性质和用户的需求,您不再真正受益于缓存。您的支持RDBMS应该足够快。一旦以任何方式缓存(包括EF二级缓存和ASP.NET输出缓存),您就需要立即计划如何过期缓存实体。这为您的程序员增加了更多的工作,并为您的系统提供了壮观的新的失败方式。
例如,考虑到EF的好处是关系属性的自动解析。您可以无缝地访问一个数据图表,直到您碰到一个缓存和陈旧的实体。在这种情况下,很难在检索这些实体之前终止缓存。
,但如果必须在更新上重新加载
如果您真的不想将您的架构更改为Microsoft推荐的/有意的方式。我建议您跟踪所有开放上下文(在构造时添加静态集合,删除dispose,使用终结器模式进行双重检查,以及在dispose上执行终结器抑制),并在保存管道中实现一些通用代码(有几种方法可以这样做),这些代码试图在所有开放上下文中重新加载实体。这是一种主动终止EF实体缓存的方法。这可能会影响较大集合的性能,但您可以处理一个要处理的实体的白名单或黑名单,而不是处理所有保存的实体。
就我个人而言,我很高兴我做出了改变(重组为短期上下文),长期而言,在代码可维护性和系统稳定性方面有巨大的好处。
发布于 2015-01-22 10:58:08
下面的方法强制EF向数据库请求查询,而不缓存结果:
this.context.someTable.AsNoTracking().Where(arg => arg.value == "value").Single();重要的方法调用是AsNoTracking
发布于 2015-01-22 17:33:45
如果使用MVVM,那么可以这样做:您的视图绑定到视图模型的属性类型为EntityViewModel (是实体的包装器)。所有更改都会立即出现在EntityViewModel中。如果您想撤消更改-调用方法EntityViewModel.Undo()。如果要将更改应用到实体--调用EntityViewModel.Apply()。然后可以调用方法DbContext.SaveChanges()。
public class Entity
{
public string Id { get; set; }
public string State { get; set; }
}
public class EntityViewModel : ViewModelBase
{
private string _state;
public EntityViewModel(Entity entity)
{
Entity = entity;
_state = entity.State;
}
public string State
{
get { return _state; }
set
{
if (value == _state)
return;
_state = value;
base.OnPropertyChanged("State");
}
}
public Entity Entity {get; private set; }
public void ApplyChanges()
{
Entity.State = _state;
}
public void Undo()
{
State = entity.State;
}
}这是一个很好的职责划分,适合MVVM。
https://stackoverflow.com/questions/28042161
复制相似问题