EF查询 常用IQueryable<T>拓展
作者:互联网
背景
日常使用EF查询数据时,经常会用到筛选(where
),排序(sort
),分页(skip take
)等操作。
举个简单例子
var list = dbContext.Students.Where(d => true);//筛选
if (!string.IsNullOrWhiteSpace(query.Name))
{
list = list.Where(d => d.Name.Contains(query.Name));
}
if (!string.IsNullOrWhiteSpace(query.Remark))
{
list = list.Where(d => d.Remark.Contains(query.Remark));
}
//...
var result = list.OrderBy(d => d.Id)//排序
.Skip((query.PageIndex - 1) * query.PageSize).Take(query.PageSize)//分页
.ToList();//从数据库取出数据
//获取单个实体的Name属性
var student = list.FirstOrDefault(d=>d.Name.Contains(query.Name));
var name = "";
if (student != null)
{
name = student.Name;
}
常常感觉重复性的代码过多,占用的篇幅不小,想点办法解决一下。
解决方案
where语句:封装WhereIf
拓展方法,只有当指定的condition
成立时,才执行predicate
语句。
需要注意IQueryable
和IEnumerable
的Where
方法的参数不同(Expression
表达式语句)实际用法是一样的。
public static IQueryable<T> WhereIf<T>(this IQueryable<T> source, Expression<Func<T, bool>> predicate, bool condition)
{
if (condition)
{
source = source.Where(predicate);
}
return source;
}
public static IEnumerable<T> WhereIf<T>(this IEnumerable<T> source, Func<T, bool> predicate, bool condition)
{
if (condition)
{
source = source.Where(predicate);
}
return source;
}
Page
语句:简单封装下IQueryable
和IEnumerable
分页方法,只是精简了一下而已。
public static IQueryable<T> DataPage<T>(this IQueryable<T> source, int pageNumber, int pageSize)
{
if (pageNumber <= 1)
{
if (pageSize == int.MaxValue)
{
return source;
}
return source.Take(pageSize);
}
else
{
return source.Skip((pageNumber - 1) * pageSize).Take(pageSize);
}
}
Sort
语句:通过拼接Sort排序字符串 这里需要引入一个System.Linq.Dynamic.Core
,支持查询字符串拼接,进行动态查询。
public static IQueryable<T> DataSort<T>(this IQueryable<T> source, string sortExpression)
{
try
{
var sortStrs = sortExpression.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
var defaultOrder = "desc";
if (sortStrs.Length == 2)
{
defaultOrder = sortStrs[1];
}
if (typeof(T).GetProperty("Id") != null && sortStrs[0] != "Id")
{
source = source.OrderBy(sortStrs[0] + " " + defaultOrder + ",Id desc");
}
else
{
source = source.OrderBy(sortStrs[0] + " " + defaultOrder);
}
return source;
}
catch (Exception)
{
return source;
}
}
组合一下来个DataList
public static IQueryable<T> DataList<T>(this IQueryable<T> source, int page = 1, int rows = int.MaxValue, string sort = "Id", string order = "desc")
{
return source.DataSort(sort, order).DataPage(page, rows);
}
获取单个对象的语句ProDefault
/// <summary>
/// 获取一个对象的属性,对象如果为空,则返回属性的默认值
/// </summary>
/// <typeparam name="TSource">对象类型</typeparam>
/// <typeparam name="T">返回值类型</typeparam>
/// <param name="entity">需要判空的对象</param>
/// <param name="func">执行函数</param>
/// <param name="t">默认值</param>
/// <returns></returns>
public static T ProDefault<TSource, T>(this TSource entity, Func<TSource, T> func, T t = default(T)) where TSource : class
{
if (entity != null)
{
return func(entity);
}
return t;
}
对照文章最开始的例子,用上这些封装后的方法试试。
list = list.WhereIf(d => d.Name.Contains(query.Name), !string.IsNullOrWhiteSpace(query.Name));
list = list.WhereIf(d => d.Remark.Contains(query.Remark), !string.IsNullOrWhiteSpace(query.Remark));
var result = list.DataList(query.PageIndex, query.PageSize).ToList();
var name = list.FirstOrDefault().ProDefault(d => d.Name, "");
总结
本文简单介绍一下个人日常开发过程中常用的一些封装方法。那么有没有可能再简单一点,连这些方法都不需要写了呢?只要传入一个Query
对象就可以直接得到结果呢?
答案当然是可以的,这里就简单介绍下思路,具体的实现方式就留着以后再说了~
通过反射获取查询对象中的数据,拼接查询字符串,借助
System.Linq.Dynamic.Core
插件的拓展方法,进行数据查询。
深究其原理,最终还是将查询字符串,处理为相应的表达式树Expression
。那么,我们是不是也可以自己来拼接表达式树呢~
System.Linq.Dynamic.Core
地址:https://github.com/zzzprojects/System.Linq.Dynamic.Core
标签:Name,IQueryable,EF,list,查询,source,var,query 来源: https://www.cnblogs.com/cplemom/p/14354753.html