7

我遇到了似乎是一个常见问题:我正在更新数据库中的值,但是EF使用其原始内存副本的对象,并且这些更改的值不反映在显示的数据中。我明白这是为什么,但我无法找出解决方法。如何在EF 4.1 RC的DbContext级别关闭更改跟踪?

最常见的解决方案似乎是设置MergeOptions.NoTracking完全关闭更改跟踪(或在查询时使用AsNoTracking()扩展方法),并在每次访问对象时强制刷新,这对我的目的来说很好。

我有一个通用的基础库这我的其他存储库继承:

public abstract class RepositoryBase<T> where T : class 
{ 
    private readonly IDbSet<T> _dbset; 
    private readonly IUnitOfWork _unitOfWork; 

    protected RepositoryBase(IUnitOfWork unitOfWork) 
    { 
     _unitOfWork = unitOfWork; 
     _dbset = _unitOfWork.Database.Set<T>(); 
    } 

    public virtual IQueryable<T> All() 
    { 
     return _dbset; 
    } 

    // Some other IQueryable methods here (Query, GetByProductCode etc) 

    public virtual T Get(long id) 
    { 
     return _dbset.Find(id); 
    } 
}  

而一个DbContext这样的:

public class Db : DbContext 
{ 
    private IDbSet<Product> _products; 

    public IDbSet<Product> Products 
    { 
     get { return _products ?? (_products = DbSet<Product>()); } 
    } 

    public virtual IDbSet<T> DbSet<T>() where T : class 
    { 
     return Set<T>(); 
    } 

    public virtual void Commit() 
    { 
     base.SaveChanges(); 
    } 
} 

如果我改变我的仓库的All()方法这样的:

public virtual IQueryable<T> All() 
{ 
    return _dbset.AsNoTracking(); 
} 

我得到想要的结果 - 当显示产品的页面被刷新时,反映数据库中的更新。但是,我不能在Get()方法中执行此操作,因为该扩展方法仅适用于IQueryable

理想情况下,我想在DbContext级别关闭此功能,因为我永远不需要更改跟踪,但似乎没有明显的方法来完成此操作,并且关于此主题的文档几乎为零(除非有人能指点我一些?请!)。

我尝试添加一个构造函数的DbContext这些配置选项禁用:

public Db() 
{ 
    base.Configuration.ProxyCreationEnabled = false; 
    base.Configuration.AutoDetectChangesEnabled = false; 
} 

但我必须承认我只是在猜测他们真正做(我只找到他们通过查看源代码),并且它们似乎没有任何影响。

任何帮助将不胜感激。如果更多的信息/代码可以帮助,请让我知道。

回答

6

如果您希望每次不想使用Find方法时强制上下文获取新数据。 Find方法始终首先查询内部存储。用这个代替:

public virtual T Get(long id) 
{ 
    return All().SingleOrDefault(e => e.Id == id); 
} 

但我不明白你需要什么?你是什​​么意思:

在数据库中更新反映 显示产品 页面被刷新

语境是工作单位时。它应该用作工作单元 - 在Web应用程序或Web服务中,它意味着为每个请求创建新的上下文实例。在winforms/wpf应用程序中,它意味着每个逻辑块使用上下文(每个演示者等)。正因为如此,您只能在非常特定的情况下才需要此功能,但您需要全局使用它。你的描述看起来好像你正在重复使用completely bad solution的请求中的上下文。对于每个请求重新创建上下文没有性能成本。

+0

感谢您的回答。我认为我*是为每个请求创建一个新的上下文,但是由于您在这里指出的内容,我怀疑我的Ninject配置中可能会出现错误,我会明天再检查并报告回来! – 2011-03-31 20:20:40

+0

看来这是问题所在。我没有为每个请求创建一个新的DbContext - 或者说,Ninject不是,即使我已经在注入中指定了'InRequestScope()'。我认为这是一个单独的问题,但感谢您的帮助。 – 2011-04-01 09:17:42

+0

我已经接受了这个答案,即使它不直接*回答这个问题,因为它确实让我找到了解决方案。 – 2011-04-01 09:38:18