EntityFramework用法和常見問題


優化建議

  1. 盡可能把操作放在server端(數據庫)
  2. 把數據獲取到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();
    }
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM