假设我有这条线:

var eggs = db.Nests.Single(b => b.id = 20).Birds.FirstOrDefault().Eggs;

在我的探查器跟踪中,我看到正在执行多个命令:
SQL:BatchString
SELECT TOP (2)
[Extent1].[id]
...
FROM [dbo].[Nest] AS [Extent1]
WHERE 20 = [Extent1].[id]
SQL:BatchCompleted

RPC:Completed
exec sp_executesql N'SELECT
[Extent1].[Id] AS [Id],
...
FROM [dbo].[Bird] AS [Extent1]
WHERE [Extent1].[NesId] = @EntityKeyValue1',N'@EntityKeyValue1 int',@EntityKeyValue1=20

RPC:Completed
exec sp_executesql N'SELECT
[Extent1].[Id] AS [Id],
...
FROM [dbo].[Egg] AS [Extent1]
WHERE [Extent1].[BirdId] = @EntityKeyValue1',N'@EntityKeyValue1 int',@EntityKeyValue1=13

所有这些命令都是在同一个请求中执行的,还是每个命令都有往返?

此外,我能否确认这是编写上述内容的最有效方法:
var eggs = db.Nests.Include("Birds")
           .Single(b => b.id = 20)
           .Birds.Include("Eggs")
           .FirstOrDefault()
           .Eggs;

或者显式连接会更好吗?

最佳答案

首先,您在第一个示例中得到多个查询是完全正常的。除非您在第二个示例中使用 Include(),否则访问任何导航属性都会生成一个新的 SQL 查询。

我不确定您的数据库架构是如何布局的,但假设 Birds 有一个名为 NestsId_Nest 外键,您可以将此查询重写为:

var eggs = db.Birds.Include("Eggs")
                   .First(x => x.Id_Nest == 20)
                   .Eggs
                   .ToList();
Include() 生成与显式 join 大致相同的代码,因此无需担心代码不同。至于往返,如果您指的是 Web 服务器和数据库之间的往返,那么是的,每个查询可能都有一次往返。不过,如果连接保持打开状态,这并不是什么大问题。但最好通过 joinInclude() 一次性获得所需的一切,而不是点击 db 3 次。

10-05 18:54