您现在的位置是:首页 >学无止境 >C#LinqToSql性能优化网站首页学无止境

C#LinqToSql性能优化

包达叔 2024-07-14 06:01:02
简介C#LinqToSql性能优化
  1. 一定要写Select

不写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 });

  1. 非必要不触发SQL执行

以下函数会触发生成SQL并执行,所以不能随便用,只用在必要的地方
for循环中一定不能用

GetAllListAsync/GetAllList
FirstAsync/First
FirstOrDefaultAsync/FirstOrDefault
ToListAsync/ToList
GetAsync/Get
  1. 主键不是Id的时候使用Get/GetAsync方式时必须添加入参

没有入参时,生成的脚本里面的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;
}
  1. Queryable内尽量不要带函数,否则会导致全表查询

下面的Linq中的ToString()无法翻译为SQL,产生的SQL是全表查询,再到内存中进行过滤。

var entitty =  _xxxRepository.GetAll()
	.Where(t =>  t.BillNo.ToString() == "20221226001")
	.ToList();

如下已知安全的函数,可以放心在linq中使用:

Contains =sql的 like
日期类型的.Date
  1. 连表查询尽可能不要带函数

如下代码中的OrderByDescending会导致两个全表查询,再到内存中进行连接

var entitty = _XXXMasterRepository.GetAll()
	.Join(_XXXDetailRepository.GetAll().OrderByDescending(t => t.BillNo))
	.Where(t => t.BillNo == "20221226001")
  1. 连接中不用匿名类

//这个写法会产生两个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;
}
  1. 不要对导航属性进行过滤或map

//有问题的写法
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();
风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。