[英]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.