1. 禁用延遲載入
延遲載入是常見的方式,Entity Framework在需要時可以自動為一個實體的例項獲取關聯的資料。
Entity Framework自動延遲載入需要同時滿足以下3個條件:
(1)DbContext.Configuration.LazyLoadingEnabled = true (預設為true)
(2)DbContext.Configuration.ProxyCreationEnabled = true (預設為true)
(3)POCO類必須是public而非sealed,且集合屬性使用Virtual修飾,這樣Entity Framework才能Override以包含延遲載入。
延遲載入示例:
using (var ctx = new LibingContext()) { var category = ctx.Categories.Find(1); foreach (var product in category.Products) { Console.WriteLine(product.ProductName); } }
EntityFramework禁用延遲載入:
public class LibingContext : DbContext { public LibingContext() : base("Name=LibingContext") { // 禁用延遲載入 this.Configuration.LazyLoadingEnabled = false; this.Configuration.ProxyCreationEnabled = false; } }
2. AsNoTracking()與Attach()
對於只讀操作,強烈建議使用AsNoTracking進行資料獲取,降低資料獲取所需的時間。
由於沒有受到DbContext的跟蹤,利於對資料及時性要求高的資料查詢。
使用AsNoTracking查詢出來的資料,要進行刪除時,需使用Attach()。
using (var ctx = new LibingContext()) { var products = ctx.Products .AsNoTracking() .ToList(); var product = products.Where(t => t.ProductID == 1).FirstOrDefault(); //// 修改不用Attach //product.ProductName = "新名稱"; //ctx.Entry(product).State = EntityState.Modified; ctx.Set<Product>().Attach(product); ctx.Entry(product).State = EntityState.Deleted; ctx.SaveChanges(); }
注:查詢過程Select對映不需要加AsNoTracking()
var products = ctx.Products .Select(t => new { t.ProductID, t.ProductName }) .ToList();
3. AsNonUnicode
using (var ctx = new LibingContext()) { var products = ctx.Products .Where(t => t.ProductName == "商品") .ToList(); }
SELECT [Extent1].[ProductID] AS [ProductID], [Extent1].[CategoryID] AS [CategoryID], [Extent1].[ProductName] AS [ProductName], [Extent1].[UnitPrice] AS [UnitPrice], [Extent1].[UnitsInStock] AS [UnitsInStock] FROM [dbo].[Product] AS [Extent1] WHERE N'商品' = [Extent1].[ProductName]
using System.Data.Entity;
using (var ctx = new LibingContext()) { var products = ctx.Products .Where(t => t.ProductName == DbFunctions.AsNonUnicode("商品")) .ToList(); }
SELECT [Extent1].[ProductID] AS [ProductID], [Extent1].[CategoryID] AS [CategoryID], [Extent1].[ProductName] AS [ProductName], [Extent1].[UnitPrice] AS [UnitPrice], [Extent1].[UnitsInStock] AS [UnitsInStock] FROM [dbo].[Product] AS [Extent1] WHERE '商品' = [Extent1].[ProductName]
EF正常情況生成的SQL會在前面帶上“N”,加上DbFunctions.AsNonUnicode生成的SQL沒有“N”。“N”是將字串作為Unicode格式進行儲存。
.Net字串是Unicode格式,SQL中帶“N”會進行資料轉換,無法使用索引,只能全表掃描。
DbFunctions.AsNonUnicode()讓.Net將其作為一個非Unicode來處理。
在進行字串查詢或者比較時建議用AsNonUnicode()方法來提高查詢效能。
4. 使用AutoMapper查詢DTO
查詢需要的欄位:DTO
using AutoMapper; using AutoMapper.QueryableExtensions;
using (var ctx = new LibingContext()) { Mapper.Initialize(cfg => cfg.CreateMap<Product, ProductDTO>()); var products = ctx.Products .ProjectTo<ProductDTO>() .ToList(); }