解决 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);
}
解决 EF where<T>(func) 查询的一个性能问题的更多相关文章
- 解决 EF 分层查询的一个性能问题[转]
前两年帮朋友 做了个网吧管理软件,采用动软的三层架构 sql语句生成的.最近因功能变更 要改动,而我这段正在做asp.net mvc +ef+autofac的一个电商网站.索性 就把原来的底层全重新了 ...
- 深入理解 EF Core:使用查询过滤器实现数据软删除
原文:https://bit.ly/2Cy3J5f 作者:Jon P Smith 翻译:王亮 声明:我翻译技术文章不是逐句翻译的,而是根据我自己的理解来表述的.其中可能会去除一些本人实在不知道如何组织 ...
- 疑难杂症——EF+Automapper引发的查询效率问题解析
前言:前面总结了一些WebApi里面常见问题的解决方案,本来打算来分享下oData+WebApi的使用方式的,奈何被工作所困,只能将此往后推了.今天先来看看EF和AutoMapper联合使用的一个问题 ...
- 第二十三节: EF性能篇(三)之基于开源组件 Z.EntityFrameWork.Plus.EF6解决EF性能问题
一. 开篇说明 EF的性能问题一直以来经常被人所吐槽,究其原因在于“复杂的操作在生成SQL阶段耗时长,且执行效率不高”,但并不是没有办法解决,从EF本身举几个简单的优化例子: ①:如果仅是查询数据,并 ...
- 解决EF没有生成字段和表说明
找了很多资料,终于找到一篇真正能解决ef生成字段说明,注释的文章,收藏不了,于是转载 本文章为转载,原文地址 项目中使用了EF框架,使用的是Database-First方式,因为数据库已经存在,所以采 ...
- mysql根据逗号分割的字符串去关联查询另外一个表的数据
1.说明 在做显示数据的时候,一个字段会存那种逗号分割的字符串,那如何去根据逗号分割字符串去查询另一个表的数据呢? 首先我们查看一下需要显示的数据 select * from company wher ...
- EF Core 的关联查询
0 前言 本文会列举出 EF Core 关联查询的方法: 在第一.二.三节中,介绍的是 EF Core 的基本能力,在实体中配置好关系,即可使用,且其使用方式,与编程思维吻合,是本文推荐的方式. 第四 ...
- MySQL GROUP_CONCAT函数使用示例:如何用一个SQL查询出一个班级各个学科第N名是谁?
如何用一个SQL查询出一个班级各个学科第N名是谁? 首先贴出建表语句,方便大家本地测试: -- 建表语句 CREATE TABLE score ( id INT NOT NULL auto_incre ...
- Oracle一个用户查询另一个用户的表数据
1.两个用户是在不同的库,需要建立dblink 2.属于同一个库的不同用户 1)方法一:使用"用户名."的方式访问 例如:要从USER1账号访问USER2中的表TABLE2 A. ...
随机推荐
- (转)vim编辑器操作命令大全-绝对全
周六了,熟悉熟悉vim 命令 学习链接: vim命令大全 http://blog.csdn.net/scaleqiao/article/details/45153379 vim命令小技巧 http:/ ...
- java命令行版的ATM
import java.util.*;public class Jatm{ static String user = "123"; static String password = ...
- Go:闭包
闭包就是一个函数和与其相关的引用环境组合的一个整体(实体). package main import "fmt" func add() func(int) int { i := 0 ...
- Django加载静态文件失败,已解决
1.css文件以及js文件要放在static目录下,static和templates属于同级目录 2.在Django项目的同名项目文件的setting.py中,最后添加静态文件夹static目录路径 ...
- SVM简单上手示例
转载自 百度知道 id:风_南(https://zhidao.baidu.com/usercenter?uid=e9904069236f25705e799313) 转载只为方便学习复习,侵删. 在用s ...
- power coefficient calculation -- post processing
input: unscaled moment of one bladeoutput: power coefficient of a 3-blades wind/tidal turbine matlab ...
- Promise对象和回调函数,解决异步数据传递问题
下面的代码例子,均已小程序的异步请求数据为案例来说明 1.利用回调函数,来解决异步数据传递问题 异步操作api.js const getBooks = (url, callback) => { ...
- POJ 1226 Substrings
Substrings Time Limit: 1000ms Memory Limit: 10000KB This problem will be judged on PKU. Original ID: ...
- HXY烧情侣(洛谷 2194)
题目描述 众所周知,HXY已经加入了FFF团.现在她要开始喜(sang)闻(xin)乐(bing)见(kuang)地烧情侣了.这里有n座电影院,n对情侣分别在每座电影院里,然后电影院里都有汽油,但是要 ...
- Django Rest FrameWork再练习
可能有重构目前应用的需求,rest framework是值得有必要深入去了解的. 所以,这应该是第三次看官方文档来练习, 希望能获取更深入的记忆. __author__ = 'CHENGANG882' ...