gpt4 book ai didi

sql - EF4.2 额外的左外连接到同一个表

转载 作者:行者123 更新时间:2023-11-30 23:49:05 25 4
gpt4 key购买 nike

我知道已经有一些关于此的问题,大多数与已解决的旧问题或多个表有关。我看到的任何其他“左外连接”问题都没有涉及这个问题,我在同一个查询中得到一个 INNER JOINLEFT 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?

最佳答案

我已经看到类似的问题了。我们可以称之为错误或功能。简单的 EF 查询生成远非理想。 ADO.NET 团队修复了每个主要版本的一些问题。我目前没有安装 June CTP 2011 以验证它是否也发生在下一版本的第一个预览中。

编辑:

根据 this answer 2011 年 6 月 CTP 中修复了类似问题。

关于sql - EF4.2 额外的左外连接到同一个表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9799136/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com