[英]EF4.2 extra left outer join to same table
我知道有一些关于这个的问题,大多数都与已解决的旧问题或多个表有关。 我看到的任何其他“左外连接”问题都没有涉及这个问题,我在同一个查询中得到一个INNER JOIN
和LEFT OUTER JOIN
到同一个表。
表格大纲:
Users: id (PK)
Name (VARCHAR)
ProfileImageUri (VARCHAR)
Locations: id (PK)
LocationBPNTips: id (PK)
TipText (VARCHAR)
CreatedAt (Datetime)
UserId (int) (FK to User.id, navigation property is called User)
LocationId (int) (FK to Location.id)
(还有更多,但不相关:))
在我的场景中,我通过投影执行对引用表的查询,我得到一个额外的左外连接,这是我运行的( 注释部分与问题无关,注释掉更清晰的SQL,EF执行排序权限) (甚至比我想象的更好:))):
LocationBPNTips
.Where(t => t.LocationId == 33)
//.OrderByDescending(t => intList.Contains(t.UserId))
//.ThenByDescending(t => t.CreatedAt)
.Select(tip => new LocationTipOutput
{
CreatedAt = tip.CreatedAt,
Text = tip.TipText,
LocationId = tip.LocationId,
OwnerName = tip.User.Name,
OwnerPhoto = tip.User.ProfileImageUri
}).ToList();
这就是生成的SQL
SELECT
[Extent1].[LocationId] AS [LocationId],
[Extent1].[CreatedAt] AS [CreatedAt],
[Extent1].[TipText] AS [TipText],
[Extent2].[Name] AS [Name],
[Extent3].[ProfileImageUri] AS [ProfileImageUri]
FROM [dbo].[LocationBPNTips] AS [Extent1]
INNER JOIN [dbo].[Users] AS [Extent2] ON [Extent1].[UserId] = [Extent2].[Id]
LEFT OUTER JOIN [dbo].[Users] AS [Extent3] ON [Extent1].[UserId] = [Extent3].[Id]
WHERE 33 = [Extent1].[LocationId]
如您所见, LEFT OUTER JOIN
在INNER JOIN
的同一个表上完成
我认为最佳代码将是(注意,我手动将Extent3重命名为Extent2,并添加了注释。这不是由EF生成的!) - 使用我当前的数据,运行速度提高了约22%(排序时,这个%应该更高,没有排序),因为不需要额外的加入..
SELECT
[Extent1].[LocationId] AS [LocationId],
[Extent1].[CreatedAt] AS [CreatedAt],
[Extent1].[TipText] AS [TipText],
[Extent2].[Name] AS [Name],
[Extent2].[ProfileImageUri] AS [ProfileImageUri]
FROM [dbo].[LocationBPNTips] AS [Extent1]
INNER JOIN [dbo].[Users] AS [Extent2] ON [Extent1].[UserId] = [Extent2].[Id]
--LEFT OUTER JOIN [dbo].[Users] AS [Extent3] ON [Extent1].[UserId] = [Extent3].[Id]
WHERE 33 = [Extent1].[LocationId]
我尝试过的不同查询(投影是这些中的匿名类型):
LocationBPNTips
.Where(t => t.LocationId == 33)
//.OrderByDescending(t => intList.Contains(t.UserId))
//.ThenByDescending(t => t.CreatedAt)
.Select(tip => new
{
CreatedAt = tip.CreatedAt,
Text = tip.TipText,
LocationId = tip.LocationId,
OwnerName = tip.User,
OwnerPhoto = tip.User
}).ToList()
SQL输出搞砸了,它以与上面相同的格式选择整个用户表两次,内部然后左外部。 我认为我在理论上可以看到为什么会发生这种情况,因为我要求两次数据 - 尽管它可以在内存中完成,而不是由SQL进行额外的连接 - 但在我的情况下我没有要求数据两次,我只询问一次不同的列。 我做了这个测试,看看双连接是否一致。
我也试过跑:
LocationBPNTips
.Where(t => t.LocationId == 33)
.Select(tip => new
{
CreatedAt = tip.CreatedAt,
Text = tip.TipText,
LocationId = tip.LocationId,
OwnerName = tip.User.Name
}).ToList()
这个按预期返回了干净的单内连接,但这不是我想要做的
所以问题是 :这是一个错误吗? 我错误地使用EF吗?
我已经看过类似的问题了。 我们可以称之为bug或功能。 简单的EF查询生成远非理想。 ADO.NET团队修复了每个主要版本的一些问题。 我目前没有安装June CTP 2011以验证它是否也出现在下一版本的第一个预览中。
编辑:
根据这个答案,类似的问题在2011年6月CTP修复。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.