EF-查询缓存

同一个DbContext实例,EF会对查询过的数据进行缓存。对DbContext的生存期的管理需根据当前的应用来处理(如web、win),尽量不要采用全局的DbContext。也可在查询中采用AsNoTracking避免从缓存中取数据。

1、问题

构建一个全局的或某个业务场景内唯一的DbContext

public OTBll()
{
  efContext = new AppDbContext();
  this.OT_DataFlowRepository = new EFRepository<OT_DataFlow>(efContext); 

在此场景内间隔查询数据

HR_SignSealPdf entity =context.HR_SignSealPdf.FirstOrDefault(e =>
  e.SignId == item.SignId && e.Cate == item.Cate);
entity.PdfUploadErrs += 1;

  

SSMS修改PdfUploadErrs后,仍会从entity.PdfUploadErrs的值上累加

UPDATE HR_SignSealPdf SET PdfUploadErrs=0

  

2、解决办法

(1)每次构建一个新的DbContext实例,使用完毕就释放

using (var context = new AppDbContext())
{
...
}

(2)AsNoTracking返回新的查询实体

efContext.HR_SignSealPdf.AsNoTracking()

反编译的代码

/// <summary>返回一个新查询,其中返回的实体将不会在 <see cref="T:System.Data.Entity.DbContext" /> 或 <see cref="T:System.Data.Entity.Core.Objects.ObjectContext" /> 中进行缓存。此方法通过调用基础查询对象的 AsNoTracking 方法来运行。如果基础查询对象没有 AsNoTracking 方法,则调用此方法将不会有任何影响。</summary>
    /// <returns>应用 NoTracking 的新查询,如果不支持 NoTracking,则为源查询。</returns>
    /// <param name="source">源查询。</param>
    public static IQueryable AsNoTracking(this IQueryable source)
    {
      System.Data.Entity.Utilities.Check.NotNull<IQueryable>(source, nameof (source));
      DbQuery dbQuery = source as DbQuery;
      if (dbQuery == null)
        return QueryableExtensions.CommonAsNoTracking<IQueryable>(source);
      return (IQueryable) dbQuery.AsNoTracking();
    }

  

3、优化

(1)web端可考虑在当前操作线程内定义个唯一的DbContext,以提高效率

//返回当前线程内的数据库上下文,如果当前线程内没有上下文,那么创建一个上下文,并保证上线问实例在线程内部是唯一的
public static VpoEntities GetCurrentDemoContext()
{
	//CallContext:是线程内部唯一的独用的数据槽(一块内存空间)
	//传递DbContext进去获取实例的信息,在这里进行强制转换。
	VpoEntities dbContext = CallContext.GetData("DbContext") as VpoEntities;
	if (dbContext == null) //线程在数据槽里面没有此上下文
	{
		dbContext = new VpoEntities(); //如果不存在上下文的话,创建一个EF上下文
		var adapter = (IObjectContextAdapter)dbContext;
		var objectContext = adapter.ObjectContext;
		objectContext.CommandTimeout = 1800;

		//我们在创建一个,放到数据槽中去
		CallContext.SetData("DbContext", dbContext);
	}
	return dbContext;
}

  

posted on 2019-01-11 09:26  村_长  阅读(2070)  评论(0编辑  收藏  举报

导航