在日常使用EF框架查询数据库时,有时传入的参数为空,那么我们应该把该条件排除,不应列入组装的sql中,本篇文件以分页查询为例介绍EF框架的单表、多表的多条件查询,参数为空时排除条件。
public class MyDbContext : DbContext
{
public DbSet<人员信息> PersonBasic{ get; set; }
public DbSet<考核信息> Assess{ get; set; }
}
用于映射到数据库表的实体类型。也就是数据库的表和字段
public class 人员信息
{
public int Id { get; set; }//id
public 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;
}
///
/// 获取列表
///
///
///
[Route("api/Test/GetList")]
public dynamic GetListAsync(InputDto input)
{
return GetEFList(input,_context);
}
}
}
using (var context = new MyDbContext())
{
var entities = context.Entities.ToList();
}
///
/// 原生ef查询
///
///
///
public PagedResultDto<OutPutDto> GetEFList(InputDto input, MyDbContext _context)
{
//机构信息传来的形式为 37,38,39
string[] 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 那么根据身份证去重(一个人会有多条数据) 查最大的id
query = 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()
.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.IdNumber
where
(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 kh
group x by x.IdNumber into g
where g.Count() > 1
select g.Max(x => x.Id)).Contains(a.Id))
orderby a.Id descending
select 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映射成OutPutDto
List<OutPutDto> aaa = pageData.Adapt<List<OutPutDto>>();
return new {items=pageData,total=count};
}
end
看完此篇文章后是不是感觉瞬间豁然开朗?