如何在EF 4.1 RC中关闭DbContext级别的更改跟踪?

Mar*_*ell 7 c# entity-framework change-tracking ef-code-first entity-framework-4.1

我遇到了一个似乎常见的问题:我正在更新数据库中的值,但EF正在使用其原始的内存副本,并且这些更改的值不会反映在显示的数据中.我理解为什么会这样,但我无法找到解决方法.

最常见的解决方案似乎是设置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);
    }
}    
Run Code Online (Sandbox Code Playgroud)

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();
    }
}
Run Code Online (Sandbox Code Playgroud)

如果我改变了All()我的存储库的方法:

public virtual IQueryable<T> All()
{
    return _dbset.AsNoTracking();
}
Run Code Online (Sandbox Code Playgroud)

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

理想情况下,我想在DbContext关卡中将其关闭,因为我永远不需要更改跟踪,但似乎没有明显的方法可以做到这一点,并且关于这个主题几乎没有文档(除非有人可以指出我来一些?拜托!).

我尝试在DbContext禁用这些配置选项的情况下添加构造函数:

public Db()
{
    base.Configuration.ProxyCreationEnabled = false;
    base.Configuration.AutoDetectChangesEnabled = false;
}
Run Code Online (Sandbox Code Playgroud)

但我必须承认,我只是猜测他们真正做了什么(我只是通过查看源代码才发现它们),但它们似乎没有任何影响.

任何帮助将不胜感激.如果有更多信息/代码可以提供帮助,请告诉我们.

Lad*_*nka 6

如果您希望每次不想使用Find方法时强制上下文获取新数据.Find方法总是首先查询内部存储.请改用:

public virtual T Get(long id)
{
    return All().SingleOrDefault(e => e.Id == id);
}
Run Code Online (Sandbox Code Playgroud)

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

刷新显示产品的页面时,将反映数据库中的更新

语境是工作单元.它应该用作工作单元 - 在Web应用程序或Web服务中,它意味着为每个请求创建新的上下文实例.在winforms/wpf应用程序中,它意味着使用每个逻辑块的上下文(每个演示者等).因此,您应该仅在非常特定的情况下才需要它,但您需要全局.您的描述似乎是在重复使用请求中的上下文,这是完全错误的解决方案.为每个请求重新创建上下文没有性能成本.