解决 EF where<T>(func) 查询的一个性能问题
前两年帮朋友 做了个网吧管理软件,采用动软的三层架构 sql语句生成的。最近因功能变更 要改动,而我这段正在做asp.net mvc +ef+autofac的一个电商网站。索性 就把原来的底层全重新了套用了我现在的架构 EF6.0+autofac+三层架构,上层的asp.net没有变。改完后发现交班页面打开巨慢。
跟踪EF生成的sql语句 发现生成的sql 有问题,查找的全表,而全表有近10万条的数据。
继续跟踪数据库的耗时查询 发现确实是这条语句占时间
为什么会这样呢,我在查询里做条件搜索了,为啥 结果不对呢?
贴出 BaseRepository.cs 的代码
public class BaseRepository<T> :IDBbase<T> where T : class
{
//实例化EF框架
protected skdbContext db = new skdbContext(); //添加
public T AddEntities(T entity)
{
db.Entry<T>(entity).State = EntityState.Added;
db.SaveChanges();
return entity;
} //修改
public bool UpdateEntity(T entity)
{
db.Set<T>().Attach(entity);
db.Entry<T>(entity).State = EntityState.Modified;
return db.SaveChanges() > ;
} //修改
public bool DeleteEntities(T entity)
{
db.Set<T>().Attach(entity);
db.Entry<T>(entity).State = EntityState.Deleted;
return db.SaveChanges() > ;
} //查询
public IQueryable<T> LoadEntities(Func<T, bool> wherelambda)
{
return db.Set<T>().Where<T>(wherelambda).AsQueryable();
}
//查询单个
public T LoadEntitie(Func<T, bool> wherelambda)
{
return db.Set<T>().FirstOrDefault<T>(wherelambda);
} //分页
public IQueryable<T> LoadPagerEntities<S>(int pageSize, int pageIndex, out int total,
Func<T, bool> whereLambda, bool isAsc, Func<T, S> orderByLambda)
{
var tempData = db.Set<T>().Where<T>(whereLambda); total = tempData.Count(); //排序获取当前页的数据
if (isAsc)
{
tempData = tempData.OrderBy<T, S>(orderByLambda).
Skip<T>(pageSize * (pageIndex - )).
Take<T>(pageSize).AsQueryable();
}
else
{
tempData = tempData.OrderByDescending<T, S>(orderByLambda).
Skip<T>(pageSize * (pageIndex - )).
Take<T>(pageSize).AsQueryable();
}
return tempData.AsQueryable();
}
}
调用代码
return jiaobanitem.LoadEntities(t => t.JiaoBanID == jiaobanID && t.GoodsID == GoodsID).FirstOrDefault();
参考 nopCommerce 修改baserepository
public class EFRepository<T> : IRepository<T> where T : class
{
//实例化EF框架
//protected YaFeiNetContext db = new YaFeiNetContext();
private DbContext _context;
private IDbSet<T> _entities; public EFRepository(DbContext context)
{
this._context = context;
} //添加
public virtual T AddEntities(T entity)
{
try
{
if(entity==null)
throw new ArgumentNullException("entity"); this.Entities.Add(entity);
this._context.SaveChanges();
return entity;
}
catch(DbEntityValidationException dbEx)
{
var msg = string.Empty;
foreach(var validationErrors in dbEx.EntityValidationErrors)
foreach (var validationError in validationErrors.ValidationErrors)
msg += string.Format("Property:{0} Error:{1}", validationError.PropertyName, validationError.ErrorMessage) + Environment.NewLine ; var fail = new Exception(msg,dbEx);
throw fail;
}
} //修改
public virtual bool UpdateEntities(T entity)
{
try
{
if (entity == null)
throw new ArgumentNullException("entity"); // this.Entities.Attach(entity);
// _context.Entry<T>(entity).State = EntityState.Modified;
return this._context.SaveChanges() > ;
}
catch (DbEntityValidationException dbEx)
{
var msg = string.Empty;
foreach (var validationErrors in dbEx.EntityValidationErrors)
foreach (var validationError in validationErrors.ValidationErrors)
msg += string.Format("Property:{0} Error:{1}", validationError.PropertyName, validationError.ErrorMessage) + Environment.NewLine; var fail = new Exception(msg, dbEx);
throw fail;
} } //修改
public virtual bool DeleteEntities(T entity)
{
try
{
if (entity == null)
throw new ArgumentNullException("entity"); //db2.Set<T>().Attach(entity);
//db2.Entry<T>(entity).State = EntityState.Deleted;
this.Entities.Remove(entity);
return this._context.SaveChanges() > ;
}
catch (DbEntityValidationException dbEx)
{
var msg = string.Empty;
foreach (var validationErrors in dbEx.EntityValidationErrors)
foreach (var validationError in validationErrors.ValidationErrors)
msg += string.Format("Property:{0} Error:{1}", validationError.PropertyName, validationError.ErrorMessage) + Environment.NewLine; var fail = new Exception(msg, dbEx);
throw fail;
} } //查询
public virtual IQueryable<T> LoadEntities(Func<T, bool> wherelambda)
{
return this.Entities.Where<T>(wherelambda).AsQueryable();
}
//查询单个
public virtual T LoadEntitie(Func<T, bool> wherelambda)
{
return this.Table.Where(wherelambda).FirstOrDefault();
}
/// <summary>
/// 根据主键查找
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
public virtual T GetById(object id)
{
return this.Entities.Find(id);
} //分页
public virtual IQueryable<T> LoadPagerEntities<S>(int pageSize, int pageIndex, out int total,
Func<T, bool> whereLambda, bool isAsc, Func<T, S> orderByLambda)
{ var tempData = this.Entities.Where<T>(whereLambda); total = tempData.Count(); //排序获取当前页的数据
if (isAsc)
{
tempData = tempData.OrderBy<T, S>(orderByLambda).
Skip<T>(pageSize * (pageIndex - )).
Take<T>(pageSize).AsQueryable();
}
else
{
tempData = tempData.OrderByDescending<T, S>(orderByLambda).
Skip<T>(pageSize * (pageIndex - )).
Take<T>(pageSize).AsQueryable();
}
return tempData.AsQueryable(); } protected virtual IDbSet<T> Entities
{
get
{
if (_entities == null)
_entities = _context.Set<T>();
return _entities;
}
} public virtual IQueryable<T> Table
{
get { return this.Entities; }
} }
同时修改调用代码 为
return jiaobanitem.Table.Where(t=>t.JiaoBanID ==jiaobanID && t.GoodsID ==GoodsID).FirstOrDefault();
问题解决 页面响应不到100ms 同时调试中 生成的sql语句已经有 查询条件了
问题出在
//查询
public IQueryable<T> LoadEntities(Func<T, bool> wherelambda)
{
return db.Set<T>().Where<T>(wherelambda).AsQueryable();
}
为了验证,我在前台直接调用
return this.context.Set<tb_e_jiaoBanItem>().Where(t => t.JiaoBanID == jiaobanID && t.GoodsID == GoodsID).AsQueryable().FirstOrDefault();
页面响应也是 100ms左右,性能没问题。直接调用 dbcontext的set<>方法 没问题。但跨了几层传递后 就有问题。并没有生成我想要的查询语句。
这个问题原来别人也碰到过 http://www.cnblogs.com/yjmyzz/archive/2008/09/06/1285564.html
如果传入Where的参数为Expression,则L2S会自动帮忙处理Expression的拼接;而如果传入的是Func,而L2S无法拼接Expression与Func,所以只好先把数据全部取出来,然后再应用Func来进行数据过滤。
代码应该修改为:
public virtual IEnumerable<T> LoadEntities(System.Linq.Expressions.Expression<Func<T,bool>> wherelambda)
{
return this.Table.Where<T>(wherelambda);
}
最新文章
- MySQL索引结构--由 B-/B+树看
- SpringMVC 对比 struts2
- Java &; Android Color-Background
- 原生 js 模拟 alert 弹窗
- MySQL优化 - 索引优化
- 由内搜推送思考Kafka 的原理
- Windows下使用console线连接思科交换机
- JAVA应用程序转换为Applet
- C语言的三目运算符
- DNS原理-HTTP原理-TCP原理
- html转成pdf,下载(html2canvas 和 jsPDF)
- django admin 导出数据简单示例
- LINUX漏洞-安全防护--防火墙相关
- U3D正播反播动画剪辑
- java分布式集群
- python3.5+ asyncio await异步详解
- 简述基于Struts框架Web应用的工作流程
- [学习笔记]fork深入理解
- python 获取项目的根路径
- VB.NET小结