Entity framework 不在 SQL 查询中使用 JOIN

Entity framework doesn't use JOIN in SQL queries

我为一对多关系编写了一些代码,从 Defect 个实例中获取 Invoice 个实例。

mydbEntities ef = new mydbEntities (); //mydbEntities is derived from DbContext
ef.Database.Log = s => System.Diagnostics.Debug.WriteLine (s);
Invoice inv = ef.Defects.Where (i => i.Id == 5).SingleOrDefault ().Invoice;

这是EDM图的一部分:

我很好奇为什么它没有调用 INNER JOIN,而是执行了 2 SQL 个查询。在我正在阅读的书中 ("Mastering Entity Framework"),在相同的情况下调用了 INNER JOIN。

调试输出:

SELECT TOP (2) 
    [Extent1].[Id] AS [Id], 
    [Extent1].[PositionId] AS [PositionId], 
    [Extent1].[InvoiceId] AS [InvoiceId], 
    [Extent1].[Count] AS [Count], 
    [Extent1].[Reason] AS [Reason]
    FROM [dbo].[Defect] AS [Extent1]
    WHERE 5 = [Extent1].[Id]


-- Executing at 6/21/2015 11:21:02 AM +05:00

-- Completed in 1 ms with result: SqlDataReader



Closed connection at 6/21/2015 11:21:02 AM +05:00

Opened connection at 6/21/2015 11:21:02 AM +05:00

SELECT 
    [Extent1].[Id] AS [Id], 
    [Extent1].[Number] AS [Number], 
    [Extent1].[InvoiceDate] AS [InvoiceDate]
    FROM [dbo].[Invoice] AS [Extent1]
    WHERE [Extent1].[Id] = @EntityKeyValue1


-- EntityKeyValue1: '1' (Type = Int32, IsNullable = false)

-- Executing at 6/21/2015 11:21:02 AM +05:00

-- Completed in 0 ms with result: SqlDataReader



Closed connection at 6/21/2015 11:21:02 AM +05:00

还有一个问题:使用 INNER JOIN 的 2 个查询对 1 个查询如何影响具有大型数据库的高负载应用程序的性能。

您应该添加 .Include(d => d.Invoice) 调用。试试这个:

    mydbEntities ef = new mydbEntities (); //mydbEntities is derived from DbContext
    ef.Database.Log = s => System.Diagnostics.Debug.WriteLine (s);
    Invoice inv = ef.Defects
        .Include(d => d.Invoice)
        .Where (i => i.Id == 5)
        .SingleOrDefault()
        .Invoice;

EntityFramework(以及大多数其他 Linq to Sql 工具)仅在一定程度上是惰性的。有一组方法可以强制查询 运行。一些例子是:

  • Single/SingleOrDefault
  • First/FirstOrDefault
  • ToList
  • ToArray

我使用的技巧是这些方法中的每一个都有一个 returns Task<T> 的异步版本。因此,如果 IDE 中的自动完成包含 SingleOrDefaultAsync,那么很明显 SingleOrDefault 会导致查询 运行.

请注意,Linq to Objects 也会出现相同的行为; ToList、Single 等中的每一个都是 eager 方法,而 return IEnumerable 是 lazy 并在第一个执行急于操作。

为了回答您的问题,Include 方法通过 return 连接数据解决了这个问题。如果您正确使用它,这将提高性能。

在您的示例中,您从对象中获取 Invoice 属性,因此正确的调用是使用 .Include(d => d.Invoice).Include("Invoice")。这两个都告诉 EF 在第一个查询中拉回 Invoice 信息。