EntityFramework Core筆記:查詢數據(3)


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


免責聲明!

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



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