我想问为什么Linq to Entities返回的连接数超过了必要的数量,以及改进它们的方法。
这是我的代码:
var items = dc.WHItems
.Select(c => new testModel()
{
ID = c.ID,
Name = c.Name,
Code = c.Code,
Discontinued = c.Discontinued,
Type = c.WHItemType.Name,
Category = c.WHItemType.WHItemCategory.Name
})
.Where(c => c.Discontinued == false)
.Take(10);
从SQL事件探查器获取结果SQL
SELECT TOP (10)
[Extent1].[ID] AS [ID],
[Extent1].[Name] AS [Name],
[Extent1].[Code] AS [Code],
[Extent1].[Discontinued] AS [Discontinued],
[Extent2].[Name] AS [Name1],
[Extent4].[Name] AS [Name2]
FROM [dbo].[WHItems] AS [Extent1]
INNER JOIN [dbo].[WHItemTypes] AS [Extent2] ON [Extent1].[WHItemTypeID] = [Extent2].[ID]
LEFT OUTER JOIN [dbo].[WHItemTypes] AS [Extent3] ON [Extent1].[WHItemTypeID] = [Extent3].[ID]
LEFT OUTER JOIN [dbo].[WHItemCategories] AS [Extent4] ON [Extent3].[WHItemCategoryID] = [Extent4].[ID]
WHERE 0 = [Extent1].[Discontinued]
然而使用LINQPad4,结果查询让我满意
SELECT TOP (10) [t0].[ID], [t0].[Name], [t0].[Code], [t0].[Discontinued], [t1].[Name] AS [Type], [t2].[Name] AS [Category]
FROM [WHItems] AS [t0]
INNER JOIN [WHItemTypes] AS [t1] ON [t1].[ID] = [t0].[WHItemTypeID]
INNER JOIN [WHItemCategories] AS [t2] ON [t2].[ID] = [t1].[WHItemCategoryID]
WHERE NOT ([t0].[Discontinued] = 1)
这是另一个代码,我尝试从库存中获取项目。表WHInventories在WHItemID和WHID上使用复合键,我认为这解释了如上所述使用'Inner Join'而不是'Left Join'的选择。
var items = dc.WHInventories
.Select(c => new testModel()
{
ID = c.WHItemID,
Name = c.WHItem.Name,
Code = c.WHItem.Code,
Discontinued = c.WHItem.Discontinued
})
.Where(c => c.Discontinued == false)
.Take(10);
SQL Profiler中的结果查询显示了额外的左外连接。为什么必须从Extent3中检索列代码?列名称和已停止使用相同的Extent2
SELECT TOP (10)
[Extent1].[WHItemID] AS [WHItemID],
[Extent2].[Name] AS [Name],
[Extent3].[Code] AS [Code],
[Extent2].[Discontinued] AS [Discontinued]
FROM [dbo].[WHInventories] AS [Extent1]
INNER JOIN [dbo].[WHItems] AS [Extent2] ON [Extent1].[WHItemID] = [Extent2].[ID]
LEFT OUTER JOIN [dbo].[WHItems] AS [Extent3] ON [Extent1].[WHItemID] = [Extent3].[ID]
WHERE 0 = [Extent2].[Discontinued]
如果我尝试显式连接,这意味着失去了拥有'导航属性'的优势。
var items = dc.WHInventories
.Join(dc.WHItems, c => c.WHItemID, d => d.ID, (c, d) => new { c, d })
.Select(c => new testModel()
{
ID = c.c.WHItemID,
Name = c.d.Name,
Code = c.d.Code,
Discontinued = c.d.Discontinued
})
.Where(c => c.Discontinued == false)
.Take(10);
SQL Profiler中的结果查询显示了我的预期。列代码现在使用Extent2
SELECT TOP (10)
[Extent1].[WHItemID] AS [WHItemID],
[Extent2].[Name] AS [Name],
[Extent2].[Code] AS [Code],
[Extent2].[Discontinued] AS [Discontinued]
FROM [dbo].[WHInventories] AS [Extent1]
INNER JOIN [dbo].[WHItems] AS [Extent2] ON [Extent1].[WHItemID] = [Extent2].[ID]
WHERE 0 = [Extent2].[Discontinued]