EF学习和使用(八)你必须知道的效率问题根源之Expression<Func<TObject, bool>>与Func<TObject, bool>
2015-10-18 19:43
716 查看
框架中加入了EF,使开发效率大大加快,但是项目做出来之后,数据稍微多一点,页面的加载速度就会非常慢。经过层层详细的排查之后,发现是项目封装的EF工具类有问题。
工具类中封装的查询方法:
方法的参数whereLambda,其类型为
并且当调用带条件参数的查询方法时,都会遇到这个问题。不过当发现问题之后,基本也就能解决问题了。随后我们发现了与
修改后的方法:
修改之前测试结果:
修改之后测试结果:
修改之后需要注意:
修改为表达式类型后按照之前的思路写可能会报错
错误原因:
因为底层方法的参数Lambda,由委托类型改为表达式类型。因此咱们写的Lambda表达式里面不能存在C#的方法,比如 ToString()、ToInt()等等。因为表达式类型不能识别。
解决方案:
将Lambda中用到的参数,在外面定义成变量。然后再放到Lambda表达式中。
举例:
总结:
工具类中封装的查询方法:
#region 按条件查询:LoadItems(Func<T, bool> whereLambda) /// <summary> /// 按条件查询 /// </summary> /// <param name="whereLambda">lambda表达式</param> /// <returns>IQueryable 泛型集合</returns> public IQueryable<T> LoadItems(Func<T, bool> whereLambda) { return MyBaseDbContext.Set<T>().Where(whereLambda).AsQueryable(); } #endregion
方法的参数whereLambda,其类型为
Func<T, bool>,在调用LoadItems方法时,通过SQL Server Profiler检测生成的sql语句,你会发现它只生成了一条查询全部结果的语句。然后通过一步步断点调试发现,将数据全部加载完毕后,还会根据查询条件whereLambda进行很多次的循环,才能把最终结果返回。
并且当调用带条件参数的查询方法时,都会遇到这个问题。不过当发现问题之后,基本也就能解决问题了。随后我们发现了与
Func<TObject, bool>非常相似的类型
Expression<Func<TObject, bool>>
Expression<Func<TObject, bool>>为表达式类型,它会带上查询条件一并生成sql语句,将查询结果返回,大大提高查询效率。
修改后的方法:
#region 按条件查询:LoadItems(Expression<Func<T, bool>> whereLambda) /// <summary> /// 按条件查询 /// </summary> /// <param name="whereLambda">lambda表达式</param> /// <returns>IQueryable 泛型集合</returns> public IQueryable<T> LoadItems(Expression<Func<T, bool>> whereLambda) { return MyBaseDbContext.Set<T>().Where(whereLambda).AsQueryable(); } #endregion
修改之前测试结果:
条件 | 结果 |
---|---|
从4W条数据中分页查询出10条查询 | 21.31 S |
条件 | 结果 |
---|---|
从4W条数据中分页查询出10条查询 | 0.28 S |
修改为表达式类型后按照之前的思路写可能会报错
LINQ to Entities 不识别方法“System.String ToString()”,因此该方法无法转换为存储表达式。 LINQ to Entities 不识别方法“…get_Item(Int32)”,因此该方法无法转换为存储表达式。
错误原因:
因为底层方法的参数Lambda,由委托类型改为表达式类型。因此咱们写的Lambda表达式里面不能存在C#的方法,比如 ToString()、ToInt()等等。因为表达式类型不能识别。
解决方案:
将Lambda中用到的参数,在外面定义成变量。然后再放到Lambda表达式中。
举例:
//修改之前 listQuestionTypeDetails = this.CurrentDal.LoadItems(u => u.ExamQuestionTypeEntity.QuestionTypeId == enQuestionType.QuestionTypeId.ToString()).ToList(); //修改之后 String questionTypeId = enQuestionType.QuestionTypeId.ToString(); listQuestionTypeDetails = this.CurrentDal.LoadItems(u => u.ExamQuestionTypeEntity.QuestionTypeId == questionTypeId ).ToList();
总结:
Expression<Func<TObject, bool>>与
Func<TObject, bool>
Func<TObject, bool>委托类型,使用这个类型执行查询时会查询表中的全部数据,加载到内存中然后在根据条件循环进行筛选。
Expression<Func<TObject, bool>>表达式类型,使用该类型作为参数时,会将查询条件一并添加到sql语句中查询出结果。
相关文章推荐
- 不要使用CSS Expression的原因分析
- 表格隔行换色 css expression
- Expression Web 2006正式发布
- javascript中expression的用法整理
- 使用.NET中的Action及Func泛型委托深入剖析
- (翻译)Java SE 8 Lambda 特性与基本原理(上)
- oracle decode function
- grep技巧 转载
- Linux下find命令错误"find: paths must precede expression"
- Linux中如何杀掉僵尸进程
- vc6-2-expression cannot be evaluated
- stddef.h
- awk中gsub和sub 的用法
- EL表达式
- Expression Designer系列工具汇总 [转载]
- 轻松理解正则表达式
- 使用EF框架的增删改查和分页的公共类
- 对一个或多个实体的验证失败。有关详细信息,请参见“EntityValidationErrors”属性。
- entity framework的配置步骤
- MVC中“The model backing the '***Context' context has changed since the database was created. ”的问题处理