1. 基本查詢
1.1 加載全部數據
using System.Linq;
using (var context = new LibingContext()) { var roles = context.Roles.ToList(); }
1.2 加載單個實體
using (var context = new LibingContext()) { var role = context.Roles.FirstOrDefault(t => t.RoleID == 1); }
using (var context = new LibingContext()) { var role = context.Roles.Find(1); }
注:Find()根據主鍵值查詢返回單個實體。
1.3 篩選條件
using (var context = new LibingContext()) { var roles = context.Roles .Where(t => t.RoleName == "管理員") .ToList(); }
2. 加載關聯數據
Entity Framework Core可以在實體模型中使用導航屬性,來加載關聯數據。
常見的3中關聯數據加載方式:
(1)預先加載(Eager Loading):關聯數據作為初始查詢的一部分從數據庫中加載
(2)顯式加載(Explicit Loading):關聯數據在后續用到時顯式指定從數據中加載
(3)延遲加載(Lazy Loading):關聯數據通過導航屬性,以透明方式從數據庫中加載
2.1 預先加載
使用Include()指定需要包含在查詢結果中的關聯數據。
using System.Linq; using Microsoft.EntityFrameworkCore;
using (var context = new LibingContext()) { var categories = context.Categories .Include(t => t.Products) .ToList(); }
2.2 顯式加載
顯式加載通過一個導航屬性DbContext.Entry(...)API。
using (var context = new LibingContext()) { var category = context.Categories.Find(1); context.Entry(category) .Collection(t => t.Products) .Load(); category.Products.ForEach(product => { Console.WriteLine("ProductID:{0},ProductName:{1}", product.ProductID, product.ProductName); }); }
顯式加載通過相關的實體的聚合運算符,而無需加載到內存的操作。
using (var context = new LibingContext()) { var category = context.Categories.Find(1); int count = context.Entry(category) .Collection(t => t.Products) .Query() .Count(); }
篩選加載到內存的關聯實體數據。
using (var context = new LibingContext()) { var category = context.Categories.Find(1); var products = context.Entry(category) .Collection(t => t.Products) .Query() .Where(t => t.UnitPrice >= 10) .ToList(); }
3. 跟蹤與非跟蹤
3.1 跟蹤查詢
Entity Framework Core跟蹤狀態的實體,在檢測到改動的情況下,調用SaveChanges()時,將持久保存數據庫中。
using (var context = new LibingContext()) { var product = context.Products.Find(1); product.UnitPrice = 100m; context.SaveChanges(); }
3.2 非跟蹤查詢
非跟蹤查詢在對查詢數據只讀情況下,可以加快執行。
using (var context = new LibingContext()) { var products = context.Products .AsNoTracking() .ToList(); }
更改默認跟蹤上下文實例級別的行為:
using (var context = new LibingContext()) { context.ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking; var products = context.Products .ToList(); }
3.3 跟蹤與投影
即使查詢的結果類型不是實體類型,如果結果包含實體類型它們將仍在默認情況下跟蹤。
在下面的查詢,它返回匿名類型的實例Category
集將跟蹤結果中。
using (var context = new LibingContext()) { var categories = context.Categories .Select(t => new { Category = t, Products = t.Products.Count() }); }
如果結果集不包含任何實體類型,會不執行任何跟蹤。
在下面的查詢,這將返回一個匿名類型使用某些實體(但不實際實體類型的實例)中的值時,沒有任何跟蹤執行。
using (var context = new LibingContext()) { var products = context.Products .Select(t => new { ProductID = t.ProductID, PrudctName = t.ProductName }); }
4. 原始SQL查詢
EntityFramework Core使用原始SQL查詢限制條件:
(1)SQL查詢返回字段必須屬於實體類型
(2)SQL查詢必須返回實體類型的所有屬性
4.1 基本原始SQL查詢
使用FromSql擴展方法,基於原始的 SQL 查詢的 LINQ 查詢。
using (var context = new LibingContext()) { var products = context.Products .FromSql("SELECT * FROM [dbo].[Product]") .ToList(); }
使用原始的 SQL 查詢來執行存儲的過程。
CREATE PROCEDURE USP_GetProducts AS BEGIN SELECT * FROM [dbo].[Product] END
using (var context = new LibingContext()) { var products = context.Products .FromSql("EXECUTE [dbo].[USP_GetProducts]") .ToList(); }
4.2 傳遞參數
SQL參數化可以防止收到SQL注入攻擊。
CREATE PROCEDURE USP_GetProductsByUnitPrice @UnitPrice DECIMAL(18, 2) AS BEGIN SELECT * FROM [dbo].[Product] WHERE [UnitPrice] >= @UnitPrice END
using (var context = new LibingContext()) { decimal unitprice = 100m; var products = context.Products .FromSql("EXECUTE [dbo].[USP_GetProducts] {0}", unitprice) .ToList(); }
using System.Data; using System.Data.SqlClient;
using (var context = new LibingContext()) { var unitprice = new SqlParameter("@UnitPrice", SqlDbType.Decimal); unitprice.Value = 100m; var products = context.Products .FromSql("EXECUTE [dbo].[USP_GetProducts] @UnitPrice", unitprice) .ToList(); }
5. 異步查詢
異步操作使用場景:當等待一個比較耗時的操作時,使用異步來釋放當前的托管線程而無需等待,不會阻塞當前線程的運行。
異步操作在主應用程序線程以外的線程中執行,應用程序可在異步方法執行其任務時繼續執行。
異步查詢在數據庫中執行查詢時可以避免阻止線程。
Entity Framework Core提供的異步查詢擴展方法包括:ToListAsync(),ToArrayAsync(),SingleAsync()等。
using System.Threading.Tasks; using Microsoft.EntityFrameworkCore;
public async Task<List<Product>> GetProductsAsync() { using (var context = new LibingContext()) { return await context.Products.ToListAsync(); } }