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