C#实体框架中的SQL请求取决于延迟加载或渴望加载

我有一个简单的联接查询,连接两个表(一个类别有很多产品):

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?

chenglong676 回答:C#实体框架中的SQL请求取决于延迟加载或渴望加载

  

...当我使用.ToList()时(急切加载)
  ...当我使用(默认)延迟加载

您正在混淆两个不同的概念。使用ToList()渴望加载不同,而惰性加载相反。它是强制执行,与之对应的是延迟执行

因此,是否使用ToList()永远不会确定LINQ查询运行时EF将生成的SQL查询数量。实体框架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; }
}

尽管如此,通常优先选择优先加载而不是延迟加载,因为它对数据库的“混乱”程度较小。

本文链接:https://www.f2er.com/3100282.html

大家都在问