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(); } }