我遇到了一个似乎很常见的问题:我正在更新数据库中的值,但 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);
}
}
And a 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;
}
但我必须承认我只是猜测它们到底做了什么(我只是通过查看源代码找到它们),而且它们似乎没有任何效果。
任何帮助将不胜感激。如果更多信息/代码有帮助,请告诉我。