实体框架5渴望加载。如何构建查询?

时间:2013-08-08 12:37:15

标签: c# entity-framework-5 eager-loading

玩EF5我注意到一些奇怪的事情。给出这两个类和一个简单的查询

public class Customer {
  public string Name { get; set; }
  public string Email { get; set; }
  ...
  public virtual IList<Order> Orders { get; set; }
} 

public class Order {
  public Customer Cust { get; set; }
  public Datetime DateOrdered { get; set; }
  ...
}

using (var ctx = new DatabaseContext(connstring))
{
 Customer c= ctx.customers.Include(x => x.orders).Where(x => x.Id == 1).Single<Customer>();

 foreach (Order o in c.orders)
 {
   Console.WriteLine(o.ToString());
 }
}

我检查了SQL Server Profiler输出,我认为查询是不必要的复杂:

SELECT 
[Project1].[Id] AS [Id], 
[Project1].[name] AS [name], 
[Project1].[C1] AS [C1], 
[Project1].[Id1] AS [Id1], 
[Project1].[customer_Id] AS [customer_Id], 
[Project1].[timeordered] AS [timeordered]
FROM ( SELECT 
    [Limit1].[Id] AS [Id], 
    [Limit1].[name] AS [name], 
    [Extent2].[Id] AS [Id1], 
    [Extent2].[customer_Id] AS [customer_Id], 
    [Extent2].[timeordered] AS [timeordered], 
    CASE WHEN ([Extent2].[Id] IS NULL) THEN CAST(NULL AS int) ELSE 1 END AS [C1]
    FROM   (SELECT TOP (2) [Extent1].[Id] AS [Id], [Extent1].[name] AS [name]
        FROM [dbo].[Customers] AS [Extent1]
        WHERE 1 = [Extent1].[Id] ) AS [Limit1]
    LEFT OUTER JOIN [dbo].[Orders] AS [Extent2] ON [Limit1].[Id] = [Extent2].[customer_Id]
)  AS [Project1]
ORDER BY [Project1].[Id] ASC, [Project1].[C1] ASC

我确定我错过了一些东西,但我不知道是什么,或者是真正的急切加载行为?

2 个答案:

答案 0 :(得分:1)

这是正常的。在您的简单情况下(1包含),您会看到EF将实际查询作为子查询,然后选择它并应用排序。

如果您尝试在单个查询中包含更多包含,您将看到行为更改,因为它将开始为每个实体执行单个查询,然后将所有查询“联合”,最后选择结果。< / p>

根据我的经验,急切加载EF导致几乎总是在性能下降,所以我建议避免它,除非你有特定需求,并且你已经深刻考虑了性能影响。

答案 1 :(得分:0)

使用Include,您说您希望一个数据库匹配,从而产生多个对象。

为了做到这一点,EF必须构建一个合适的查询进一步处理结果。假设我们有一个表A,每个A都有很多B个。特别是,有两个A,每个都有三个(不同的)B s。假设我们要求A.Include("B")。 EF构造一个具有基本结果的结果集的查询:

AId    AProp1    AProp2     BId    BAId   BProp1   BProp2
1      xxx       yyy        56     1      aaa      bbb
1      xxx       yyy        57     1      ccc      ddd
1      xxx       yyy        58     1      eee      fff
2      www       zzz        101    2      ggg      ggg
2      www       zzz        102    2      jjj      kkk
2      www       zzz        103    2      mmm      nnn
然后,

EF会使用此数据构建两个A个对象,六个B个对象,并相应地填充每个A的{​​{1}}集合。

这就是你渴望加载的要求 - 你想要更少的数据库调用,但每个数据库返回的数据更多。

此外:B列是(我猜)是一个指标列,用于说明特定C1是否有A s;而B是因为您要求TOP (2),因此它必须能够区分现有的1条记录和1条以上的记录。

相关问题