EF列表分页查询(单表、多表),排除参数为空的条件
在日常使用EF框架查询数据库时,有时传入的参数为空,那么我们应该把该条件排除,不应列入组装的sql中,本篇文件以分页查询为例介绍EF框架的单表、多表的多条件查询,参数为空时排除条件。
首先我们要有派生自DBContext类的数据上下文类,这个类代表数据库连接和数据库模型
public class MyDbContext : DbContext
{public DbSet<人员信息> PersonBasic{ get; set; }public DbSet<考核信息> Assess{ get; set; }
}
两个示例的实体类型
用于映射到数据库表的实体类型。也就是数据库的表和字段
public class 人员信息
{public int Id { get; set; }//idpublic string Name { get; set; }//姓名public string Sex{ get; set; }//性别public string Age{ get; set; }//年龄public string IdNumber{ get; set; }//身份证号 与B表身份证相同 可关联public string State{ get; set; }//状态//...
}
public class 考核信息
{public int Id { get; set; }public string Name { get; set; }public string Sex{ get; set; }public string Age{ get; set; }public string IdNumber{ get; set; }//身份证号[Column(TypeName = "date")]public DateTime? Time{ get; set; }//考核时间public string OrganCode{ get; set; }//机构编号//...
}
入参实体
public class InputDto{public string SearchText{get;set;}//一个参数可查询多个条件public string Sex{get;set;}public string StartTime{get;set;}public string EndTime{get;set;}public string OrganCode{get;set;}public string State{get;set;}public string Number{get;set;}public int PageIndex{get;set;}public int PageIndex{get;set;}
}
结果返回实体
public class OutPutDto
{public int Id { get; set; }public string Name { get; set; }public string Sex{ get; set; }public string Age{ get; set; }public string State{ get; set; }//...
}
使用dbcontext上下文类进行查询
namespace Test
{public class AppServiceTest{private readonly MyDbContext _context;public AppServiceTest(MyDbContext context){this._context = context;}/// <summary>/// 获取列表 /// </summary>/// <param name="input"></param>/// <returns></returns>[Route("api/Test/GetList")]public dynamic GetListAsync(InputDto input){return GetEFList(input,_context); }}
}
using (var context = new MyDbContext())
{var entities = context.Entities.ToList();
}/// <summary>/// 原生ef查询/// </summary>/// <param name="input"></param>/// <returns></returns>public PagedResultDto<OutPutDto> GetEFList(InputDto input, MyDbContext _context){//机构信息传来的形式为 37,38,39string[] organ = input.OrganCode?.Split(',');IQueryable<考核信息> query = null;if (string.IsNullOrWhiteSpace(input.State)){DbSet<考核信息> db = _context.考核信息;// 定义查询条件 单表 lambda表达式查询//解释一下改表达式的意思,首先db表示数据库的“考核信息”表//whereif用于判断input实体传来的参数是否为空,如果不为空则拼接该条件//第一个whereif中代表着"姓名"字段开头包含input.SearchText传来的参数,当然也可以使用Contains方法,完整意思为“姓名”包含参数 或 “身份证号”包含参数//whereif.whereif 就代表着一直and//第二个whereif代表,如果传开的参数不为空,那拼接sql 性别=传来的参数 例:sex='男'//第三个whereif,参数不为空时时间大于等于传来的参数,由于数据库是datetime类型所以要转换//第四个whereif 同上//第五个whereif 代表数据库中的in 方法的开始先将OrganCode转换为数组然后organ.Contains(x.OrganCode)使用//最后一个whereif 如果Number大于1 那么根据身份证去重(一个人会有多条数据) 查最大的idquery = db.WhereIf(!string.IsNullOrWhiteSpace(input.SearchText), x => x.姓Name.StartsWith(input.SearchText) || x.IdNumber.StartsWith(input.SearchText)).WhereIf(!string.IsNullOrWhiteSpace(input.Sex), x => x.Sex == input.Sex).WhereIf(!string.IsNullOrWhiteSpace(input.StartTime), x => x.Time >= DateTime.Parse(input.StartTime))//input.StartTime.Adapt<DateTime>().WhereIf(!string.IsNullOrWhiteSpace(input.EndTime), x => x.Time <= DateTime.Parse(input.EndTime)).WhereIf(!string.IsNullOrWhiteSpace(input.OrganCode), x => organ.Contains(x.OrganCode)).WhereIf(input.Number > 0, x => db.GroupBy(y => y.IdNumber).Where(group => group.Count() > input.Number).Select(group => group.Max(y => y.Id)).Contains(x.Id)).OrderByDescending(a=>a.Id);//将以上表达式转换为sql为//select * from 考核信息 where (Name like '王%' or IdNumber like '王%') and Sex='男' and OrganCode in('37','38') and Id in(select max(Id) from 考核信息 group by IdNumber having count(*)>1) Order By Id Desc//当然如果Number参数为0对应的sql为//select * from 考核信息 where (Name like '王%' or IdNumber like '王%') and Sex='男' and OrganCode in('37','38') Order By Id Desc}else{DbSet<考核信息> kh = _context.考核信息;DbSet<人员信息> basic = _context.人员信息;// 定义查询 多表 linq查询query = from a in kh join b in basic on a.IdNumber equals b.IdNumberwhere(string.IsNullOrWhiteSpace(input.SearchText) || a.Name.StartsWith(input.SearchText) || a.IdNumber.StartsWith(input.SearchText)) &&(string.IsNullOrWhiteSpace(input.Sex) || a.Sex == input.sex) &&(string.IsNullOrWhiteSpace(input.StartTime) || a.Time >= DateTime.Parse(input.StartTime)) &&(string.IsNullOrWhiteSpace(input.EndTime) || a.Time <= DateTime.Parse(input.EndTime)) &&(string.IsNullOrWhiteSpace(input.State) || b.State == input.State) &&(input.Number <= 0 || (from x in khgroup x by x.IdNumber into gwhere g.Count() > 1select g.Max(x => x.Id)).Contains(a.Id))orderby a.Id descendingselect a;//以上linq表达式对应的sql为//select * from 考核信息 a Inner JOIN 人员信息 b ON a.IdNumber = b.IdNumber where (a.Name like '王%' or a.IdNumber like '王%') and a.Sex='男' and a.OrganCode in('37', '38') and a.Id in(select max(Id) from 考核信息 group by IdNumber having count(*)>1) Order By a.Id Desc//当然如果number为0时//select * from 考核信息 a Inner JOIN 人员信息 b ON a.IdNumber = b.IdNumber where (a.Name like '王%' or a.IdNumber like '王%') and a.Sex='男' and a.OrganCode in('37', '38') Order By a.Id Desc}int count= query.Count();//统计总行数// 分页查询数据var pageIndex = input.PageIndex;var pageSize = input.PageSize;var pageData = query.Skip(pageSize * (pageIndex - 1)).Take(pageSize).ToList();//这里使用了Mapster中间件可以在包控制管理工具中安装 然后using Mapster;//意思是将pageData映射成OutPutDtoList<OutPutDto> aaa = pageData.Adapt<List<OutPutDto>>();return new {items=pageData,total=count};}
end
看完此篇文章后是不是感觉瞬间豁然开朗?