優化建議
- 盡可能把操作放在server端(數據庫)
- 把數據獲取到client端(應用程序)時,只選擇所需的字段。如select,減少內存的使用,增加性能
Predicate
Predicate就是linq的一個Expression對象,代表一個檢索條件,返回值為bool值,true代表獲取記錄,false則不獲取。使用And和Or方法把多個查詢串聯,判斷機制為從左到右,串聯后兩者合並為一個檢索結果,再繼續和其他語句串聯
除了直接串聯一個返回值為bool值得表達式,還可以串聯另一個Predicate對象
創建:傳入一個初始bool值,代表默認檢索調試,即初始返回值。如無其他串聯語句,當初始值為true時,相當於獲取所有記錄,為false時,相當於獲取空記錄
var predicate = PredicateBuilder.New<T>(true);
Linq多表聯查和分頁
根據篩選字段所在的表,先各自進行條件篩選,並根據主表做分頁,最后再用join關鍵字聯合查詢
var subpackageQuery = _subpackageRepository.GetAll().Where(s => s.IsDeal.Equals(1)).PageBy(input);
var tranQuery = Repository.GetAll();
var query = from subpackage in subpackageQuery
join tran in tranQuery on subpackage.TranId equals tran.Id
select new GetTranDto
{
VarietyName = subpackage.VarietyName,
BuyerName = tran.BuyerName,
TranDate = subpackage.TranDate
};
多表聯查join后再group:join后先select,然后再group,若直接group,不僅容易出錯,而且需使用兩次into,代碼繁亂,不易理解
// 壞例子
query = from entrance in query
join access in _internalAccessRepository.GetAll() on entrance equals access.Xgh into joinAccess
from j2 in joinAccess.DefaultIfEmpty()
group j2 by j2.Department into grouped
select new WelcomeStatisticItem
{
DepartmentName = grouped.Key,
RegistedCount = grouped.Count()
};
// 好例子
selectQuery = from entrance in _entranceRegRepository.GetAll()
join access in _internalAccessRepository.GetAll() on entrance equals access.Xgh
select new
{
Xgh = entrance,
Department = access.Department
};
groupQuery = from entrance in query
group entrance by entrance.Department into grouped
select new WelcomeStatisticItem
{
DepartmentName = grouped.Key,
RegistedCount = grouped.Count()
};
常見問題
The LINQ expression could not be translated
所寫的linq表達式無法轉化為SQL語句,一般原因是在linq中調用了本地(client)的方法,從而使得在數據庫端(Server)無法完成調用
Client side XXX is not supported
XXX操作不支持在Client端執行,可在XX操作之后加上select操作來解決
Missing type map configuration or unsupported mapping
把Dto中的AutoMapFrom特性改為AutoMap
使用MySQL8時可能會遇到Tls版本不一致,無法連接的問題
更新后無法及時獲取
在一個請求中,如果使用Repository.Update方法更新實體記錄,再用Repository.Get獲取實體,獲取的數據是未更新前的記錄。即使開啟事務也不生效
規避方法:不適應EF的code first,而是使用手寫sql的方式更新記錄
//[UnitOfWork]
[UnitOfWork(IsDisabled = true)]
public void UpdateRemaininAmount(PlantSubpackageCreateInput input)
{
using (var unitOfWork = _unitOfWorkManager.Begin())
{
var plantHarvest = _plantHarvestRepository.Single(p => p.HarvestId.Equals(input.HarvestId));
if (input.SubpackageType == 1)
{
plantHarvest.RemainingPackageWeight -= input.SubpackageTotal;
}
else
{
plantHarvest.RemainingPackageAmount -= input.SubpackageTotal;
}
_plantHarvestRepository.Update(plantHarvest);
_unitOfWorkManager.Current.SaveChanges();
unitOfWork.Complete();
}
}
