我有一个用于替换数据库函数的 Linq 查询。这是第一个有多个连接的,我似乎无法弄清楚为什么它返回 0 个结果。
如果您能看到任何可能导致错误返回的差异,我们将不胜感激......我一直在尝试解决它,但我应该花的时间比我应该花的时间更长。
Linq 查询
context.StorageAreaRacks
.Join(context.StorageAreas, sar => sar.StorageAreaId, sa => sa.Id, (sar, sa) => new { sar, sa })
.Join(context.StorageAreaTypes, xsar => xsar.sar.StorageAreaId, sat => sat.Id, (xsar, sat) => new { xsar, sat })
.Join(context.Racks, xxsar => xxsar.xsar.sar.RackId, r => r.Id, (xxsar, r) => new { xxsar, r })
.Where(x => x.xxsar.sat.IsManual == false)
.Where(x => x.r.IsEnabled == true)
.Where(x => x.r.IsVirtual == false)
.Select(x => new { x.xxsar.sat.Id, x.xxsar.sat.Name })
.Distinct()
.ToList();
这是由 LINQ 查询生成的查询
SELECT
[Distinct1].[C1] AS [C1],
[Distinct1].[Id] AS [Id],
[Distinct1].[Name] AS [Name]
FROM ( SELECT DISTINCT
[Extent2].[Id] AS [Id],
[Extent2].[Name] AS [Name],
1 AS [C1]
FROM [dbo].[StorageAreaRacks] AS [Extent1]
INNER JOIN [dbo].[StorageAreaTypes] AS [Extent2] ON [Extent1].[StorageAreaId] = [Extent2].[Id]
INNER JOIN [dbo].[Racks] AS [Extent3] ON [Extent1].[RackId] = [Extent3].[Id]
WHERE (0 = [Extent2].[IsManual]) AND (1 = [Extent3].[IsEnabled]) AND (0 = [Extent3].[IsVirtual])
) AS [Distinct1]
生成所需结果的 SQL 查询
SELECT DISTINCT sat.Name, sat.Id
FROM StorageAreaRacks sar
JOIN StorageAreas sa on sa.id = sar.StorageAreaId
JOIN StorageAreaTypes sat on sat.id = sa.StorageAreaTypeId
JOIN Racks r on r.id = sar.RackId
WHERE sat.IsManual = 0
AND r.IsEnabled = 1
AND r.IsVirtual = 0
最佳答案
将联接与 LINQ 方法语法结合使用难以阅读且容易出错。
将联接与 LINQ 查询语法结合使用会更好,但仍然容易出错(您可以像以前一样通过错误的键进行联接)并且不会为您提供有关联接基数的信息。
LINQ to Entities 查询的最佳方式是使用导航属性(正如 Gert Arnold 在评论中所建议的那样 - 参见 Don’t use Linq’s Join. Navigate!),因为它们没有上述缺点。
整个查询应该是这样的:
var query = context.StorageAreaRacks
.Where(sar => !sar.StorageArea.StorageAreaType.IsManual
&& sar.Rack.IsEnabled && !sar.Rack.IsVirtual)
.Select(sar => new
{
sar.StorageArea.StorageAreaType.Id,
sar.StorageArea.StorageAreaType.Name,
})
.Distinct();
或
var query = (
from sar in context.StorageAreaRacks
let sat = sar.StorageArea.StorageAreaType
let r = sar.Rack
where !sat.IsManual && r.IsEnabled && !r.IsVirtual
select new { sat.Id, sat.Name })
.Distinct();
简单、可读且几乎没有错误的地方。导航属性是 EF 最漂亮的功能之一,不要错过它们。
关于c# - 具有多个连接的 Linq 查询未给出正确的结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51657874/