一,理论部分
在 Entity Framework 中,延迟加载是一种查询优化技术,它可以减少查询的数量和复杂性。延迟加载是指只有在需要时才加载相关的数据。例如,如果一个实体有一个关联实体集合,那么在访问该集合之前,不会立即加载它。这种方式可以减少查询的数量和复杂性,从而提高查询的性能和效率。
投影查询是一种查询优化技术,它可以减少查询所返回的列的数量。当我们只需要查询一些特定的列时,使用投影查询可以减少数据库的工作量和网络带宽的消耗。例如,如果我们只需要查询客户的姓名和电话号码,那么我们可以使用以下投影查询:
var query = from c in context.Customers
select new { c.Name, c.Phone };
索引是一种优化技术,它可以加快查询的速度。在Entity Framework中,我们可以使用索引来加快查询的速度。例如,如果我们经常对客户的姓名进行查询,那么我们可以为姓名列创建索引,以加快查询的速度。
Like操作符是一种模糊查询,它可以匹配包含指定字符串的值。但是,在 Entity Framework 中,Like操作符会导致全表扫描,从而降低查询的性能和效率。因此,我们应该避免使用Like操作
二,实践部分
不写Select的时候就是Select * 会带出很多无用的字段,特别是有些大字段查询和传输都会带来性能问题。
var list = from a in list
join b in listBind on a.Idcard equals b.Idcard into lb
from bind in lb.DefaultIfEmpty() //bind是左连接后的结果
join c in listPayRecord on a.DonBloodNo equals c.DonBloodNo into pr
from payRecode in pr.DefaultIfEmpty() //左连接
select MapMulti2One<PayInfoDto>(new { bind?.BindTime, bind?.WechatUserId }, new { PayTime = payRecode?.CreationTime, payRecode?.OrderNo });
以下函数会触发生成SQL并执行,所以不能随便用,只用在必要的地方
for循环中一定不能用
GetAllListAsync/GetAllList
FirstAsync/First
FirstOrDefaultAsync/FirstOrDefault
ToListAsync/ToList
GetAsync/Get
没有入参时,生成的脚本里面的Where条件会有Id=xxx
public async Task<TraApplyBillMaster> GetXLA() {
//正确的写法
var entitty =await _xxxRepository.GetAll().FirstOrDefaultAsync(t=>t.BillNo== "20221226001");
//错误的写法
var entitty2 = await _xxxRepository.GetAsync( "20221226001");
return entitty;
}
下面的Linq中的ToString()无法翻译为SQL,产生的SQL是全表查询,再到内存中进行过滤。
var entitty = _xxxRepository.GetAll()
.Where(t => t.BillNo.ToString() == "20221226001")
.ToList();
如下已知安全的函数,可以放心在linq中使用:
Contains =sql的 like
日期类型的.Date
如下代码中的OrderByDescending会导致两个全表查询,再到内存中进行连接
var entitty = _XXXMasterRepository.GetAll()
.Join(_XXXDetailRepository.GetAll().OrderByDescending(t => t.BillNo))
.Where(t => t.BillNo == "20221226001")
//这个写法会产生两个SQL,再到内存里面Join: new { sa, se } 为匿名类,在join中无法识别出SQL
public async Task<TraApplyBillMaster> GetXLC()
{
var entitty = _xxxRepository.GetAll()
.Join(_xxx33Repository.GetAll(), sa => sa.BillNo, se => se.BillNo, (sa, se) => new { sa, se });
var entitty2 = await _xxx22Repository.GetAll()
.Join(entitty, sc => sc.BillNo, sd => sd.sa.BillNo, (sc, sd) => sd.sa)
.FirstOrDefaultAsync();
return entitty2;
}
//正确的写法: 使用定义好的类XLCDto
public async Task<XLCDto> GetXLC1()
{
var entitty = _xxxRepository.GetAll()
.Join(_xxx33Repository.GetAll(), sa => sa.BillNo, se => se.BillNo, (sa, se) => new XLCDto { BillNo=sa.BillNo, BillNoDetail=se.BillNo });
var entitty2 = await _xxx22Repository.GetAll()
.Join(entitty, sc => sc.BillNo, sd => sd.BillNo, (sc, sd) => sd)
.FirstOrDefaultAsync();
return entitty2;
}
//有问题的写法
var product = await _xxx33Repository.GetAll()
.Join(_productRepository.GetAll().Include(t => t.BasBloodVariety)
.Where(t => t.BasBloodVariety.Name !="1"), sa => sa.BasBloodVarietyId, se => se.BasBloodVariety.Id, (sa, se) => se.BasBloodVariety.Name)
.FirstOrDefaultAsync();
改成下面这样
var product = await _productRepository.GetAll().Include(t => t.BasBloodVariety).Where(t => t.BasBloodVariety.Name != "1")
.Join(_xxx33Repository.GetAll(), sa => sa.BasBloodVarietyId, se => se.BasBloodVarietyId, (sa, se) => sa).FirstOrDefaultAsync();