簡體   English   中英

C# 實體框架中的 SQL 請求取決於延遲加載或急切加載

[英]SQL requests in C# Entity Framework depending on lazy or eager loading

我有一個簡單的連接查詢,連接兩個表(一個類別有很多產品):

using (ProdContext db = new ProdContext())
{
    var query = from category in db.Categories
                join product in db.Products
                     on category.CategoryID equals product.CategoryID into productList
                select new
                       {
                           categoryName = category.Name,
                           products = productList
                       };

    foreach (var c in query)
    {
        Console.WriteLine("* {0}", c.categoryName);

        foreach (var p in c.products)
        {
             Console.WriteLine("   - {0}", p.Name);
        }
    };
}

對於課程:

class Category
{
    public int CategoryID { get; set; }
    public String Name { get; set; }
    public List<Product> Products { get; set; }
}

class Product
{
    public int ProductID { get; set; }
    public String Name { get; set; }
    public int UnitsInStock { get; set; }
    public int CategoryID { get; set; }
}

class ProdContext : DbContext
{
    public DbSet<Category> Categories { get; set; }
    public DbSet<Product> Products { get; set; }
}

通常一切正常,但是當我開始嘗試急切和延遲加載時我感到困惑,因為無論我是否在查詢末尾添加.ToList()或我的 SQL 請求總是看起來像這樣:

SELECT 
    [Project1].[CategoryID] AS [CategoryID], 
    [Project1].[Name] AS [Name], 
    [Project1].[C1] AS [C1], 
    [Project1].[ProductID] AS [ProductID], 
    [Project1].[Name1] AS [Name1], 
    [Project1].[UnitsInStock] AS [UnitsInStock], 
    [Project1].[CategoryID1] AS [CategoryID1], 
FROM 
    (SELECT 
         [Extent1].[CategoryID] AS [CategoryID], 
         [Extent1].[Name] AS [Name], 
         [Extent2].[ProductID] AS [ProductID], 
         [Extent2].[Name] AS [Name1], 
         [Extent2].[UnitsInStock] AS [UnitsInStock], 
         [Extent2].[CategoryID] AS [CategoryID1], 
         CASE WHEN ([Extent2].[ProductID] IS NULL) 
            THEN CAST(NULL AS int) ELSE 1 END AS [C1]
     FROM  
         [dbo].[Categories] AS [Extent1]
     LEFT OUTER JOIN  
         [dbo].[Products] AS [Extent2] ON [Extent1].[CategoryID] = [Extent2].[CategoryID])  AS [Project1]
ORDER BY 
    [Project1].[CategoryID] ASC, [Project1].[C1] ASC

據我了解,當我使用.ToList() (急切加載)時,它應該看起來像這樣,但是當我使用(默認)延遲加載時,它應該發送許多 sql 請求,分別詢問 foreach 循環的所有元素。 我的問題是 - 為什么沒有區別並且總是只發送一個 SQL ?

...當我使用.ToList() (渴望加載)
...當我使用(默認)延遲加載時

你混淆了兩個不同的概念。 使用ToList()預加載不同,延遲加載則相反。 它是強制執行,與之對應的是延遲執行

因此,是否使用ToList()永遠不會確定 LINQ 查詢運行時 EF 將生成的 SQL 查詢的數量。 Entity Framework 6(您的版本)總是嘗試將 LINQ 查詢轉換為一個 SQL 語句。 您有一個 LINQ 語句,因此,您將獲得一個 SQL 語句。

各種加載策略中的“加載”始終與填充導航屬性有關。 急切加載由Include方法執行。 例如:

var query = 
    from category in db.Categories
        .Include(c => c.Products)
    select category;

這將返回已加載其Products導航屬性的類別。

通過訪問已執行的 LINQ 查詢結果中的導航屬性來觸發延遲加載。 例如:

var query = db.Categories.ToList();

foreach (var c in query)
{
    Console.WriteLine("* {0}", c.categoryName);

    foreach (var p in c.Products) // <= new query triggered here.
    {
         Console.WriteLine("   - {0}", p.Name);
    }
};

為了發生延遲加載,導航屬性應定義為virtual

class Category
{
    public int CategoryID { get; set; }
    public String Name { get; set; }
    public virtual ICollection<Product> Products { get; set; }
}

通常,急切加載優於延遲加載,因為它對數據庫來說不那么“健談”。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM