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