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
信息。
我为一对多关系编写了一些代码,从 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
信息。