Entity Framework編寫建議
一、查詢
1.1 AsNoTracking() 非跟蹤查詢
在實體加上AsNoTracking()方法,返回的實體不會在System.Data.Entity.DbContext中進行快取,因此能提高查詢效能(資料量大,效能提升3到4倍)。
注:
1、實體不進行跟蹤,所以修改實體後,進行SaveChanges()修改資料不會改變。
2、如果使用Select對映,不需要加AsNoTracking()。如:
Select(item=>new { item.Id,item.Name})
1.2 Any() 確定資料是否存在
使用Any(item=>item.Id==1)
查詢效率最高,FirstOrDefault次之,Count()最差(Any和Count相差幾百倍)。
1.3 AsNonUnicode()
查詢 (item=>item.Name="lee")
和(item=>item.Name==DbFunctions.AsNonUnicode("lee"))
區別在於生成的Sql語句前者Name=N'lee',後者Name='lee',N是將字串作為Unicode格式進行儲存。
因為.Net字串是Unicode格式,在上述SQL的Where子句中當一側有N型而另一側沒有N型時,此時會進行資料轉換,也就是說如果你在表中建立了索引此時會失效代替的是造成全表掃描。用 DbFunctions.AsNonUnicode 方法來告訴.Net將其作為一個非Unicode來對待,此時生成的SQL語句兩側都沒有N型,就不會進行更多的資料轉換,也就是說不會造成更多的全表掃描。所以當有大量資料時如果不進行轉換會造成意想不到的結果。
因此在進行字串查詢或者比較時建議用AsNonUnicode()方法來提高查詢效能。
1.4 真假分頁
假:query.ToList().Skip((PageIndex - 1) * PageSize).Take(PageSize)
,把資料結果查詢出放到記憶體中,然後進行分頁。
真:query.Skip((PageIndex - 1) * PageSize).Take(PageSize).ToList()
,會把引數傳到資料庫,生成分頁Sql語句,在資料庫查詢。
1.5 按需返回列
Select(item => new { item.Id, item.CodeRuleId })
1.6 合理使用延遲載入
如果用不到導航屬性中的資料,那麼使用懶載入就行,不會載入不需要的資料到記憶體中。如果會在foreach中使用導航屬性中的資料,那麼最好是禁用懶載入,通過Include()
1.7 IQueryable和IEnumerable的區別
IQueryable返回的是查詢表示式,生成了SQL查詢語句但是還沒有與資料庫進行互動。
IEnumerable則是已經執行查詢資料庫的操作且資料儲存在了記憶體中。所以在進行條件拼接的時候一定要在IQueryable型別後面追加Where條件語句,而不是等到ToList之後再開始寫條件。
錯誤:
db.Person.ToList().Where(item => item.Id == 1)
正確:
db.Person.Where(item => item.Id == 1).ToList()
二、排序
2.1 多欄位組合排序
錯誤:.OrderBy(item=>item.Id).OrderBy(item=>itme.Name)
,生成Sql語句是Order By Name ASC。
正確:.OrderBy(item=>item.Id).ThenBy(item=>itme.Name)
,生成Sql語句是Order By Id ASC, Name ASC。
注:
1、另一種方法OrderBy(item=>new {item.Id,item.Name})
,生成Sql語句同上。
2、降序使用OrderByDescending、ThenByDescending。
三、資料操作
3.1 批量新增、修改和刪除
使用原生AddRange和RemoveRange時,會生成對應條數的Sql語句進行資料處理,可藉助第三方類庫實現一次性操作(並不生成多條Sql語句)。
第三方類庫:Entity Framework Plus是一個提高實體框架效能並克服MUST-HAVE功能限制的庫。
https://entityframework.net/zh-CN/tutorial/1000007/ef-plus