c# - 具有多个连接的 Linq 查询未给出正确的结果

标签 c# entity-framework linq join entity-framework-6

我有一个用于替换数据库函数的 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/

相关文章:

c# - 如何在 C# 中使用 Gecko

c# - 由于 Release模式下的包缩小,jQuery 崩溃

c# - 将数据类型 nvarchar 转换为 int 时出错 - 执行存储过程时

c# - Web API 应用程序中的模型分离

c# - 是否有语句将元素 T 添加到 IEnumerable<T>

c# - IEnumerable<AnonymousType#1> 的显式转换

c# - 如何返回以特定字符开头和结尾的所有单词?

c# - 无锁线程安全

c# - 使 Visual Studio 调试器以正确的应用程序为目标

c# - 错误 : The object cannot be deleted because it was not found in the ObjectStateManager