【问题标题】:Unexpected behaviour with LINQ to Entities, possible bug?LINQ to Entities 的意外行为,可能的错误?
【发布时间】:2014-07-30 19:45:27
【问题描述】:

背景
我在我的应用程序中记录搜索,并希望在统计视图中显示不同类型搜索之间的比率。

问题
我想在 LINQ 中保持尽可能高效和简洁,但考虑到可以在 LINQ 查询中使用的限制,我仍然保持清晰,所以我的尝试是这样的:

(请忽略我没有为搜索类型使用单独的实体,这是有原因的)

    var result = MyEntities.Instance.SearchStatistics
        .GroupBy(x => x.SearchType)
        .Select(y => new List<string> { { y.Key }, { SqlFunctions.StringConvert((decimal)y.Count()).Trim() } })
        .ToList();

    return Json(new
    {
        Text = result.First(x => x.ElementAt(0) == "Text").ElementAt(1),
        Organization = result.First(x => x.ElementAt(0) == "Organization").ElementAt(1),
        Subject = result.First(x => x.ElementAt(0) == "Subject").ElementAt(1),
    }, JsonRequestBehavior.AllowGet);

不过,这以一种意想不到的方式表现出来,列表列表中的结果列表得到了它在每隔一行翻转的值。

我期望 {{"Text", "123"}, {"Organization", "123"}, {"Subject", "123"},...}
而是得到了 {{"Text", "123"}, {"123", "Organization"}, {"Subject", "123"},...}

我不明白为什么,并尝试对查询进行分区

    var preresult = MyEntities.Instance.SearchStatistics
        .GroupBy(x => x.SearchType).ToList();

    var result = preresult
        .Select(y => new List<string> { { y.Key }, { y.Count().ToString(CultureInfo.InvariantCulture) } }).ToList();

现在在数据库中只执行分组查询时,它按预期工作

将 LINQ 查询的结果 sql 记录到数据库中,我得到了“错误”的结果:

SELECT [Project3].[SearchType] AS [SearchType],
       [Project3].[C2]         AS [C1],
       [Project3].[C1]         AS [C2]
FROM   (SELECT CASE
                 WHEN ([UnionAll1].[C1] = 0) THEN [GroupBy1].[K1]
                 ELSE LTRIM(RTRIM(STR(CAST([GroupBy1].[A1] AS decimal(19, 0)))))
               END             AS [C1],
               [GroupBy1].[K1] AS [SearchType],
               1               AS [C2]
        FROM   (SELECT [Extent1].[SearchType] AS [K1],
                       COUNT(1)               AS [A1]
                FROM   [app].[SearchStatistic] AS [Extent1]
                GROUP  BY [Extent1].[SearchType]) AS [GroupBy1]
               CROSS JOIN (SELECT 0 AS [C1]
                           FROM   (SELECT 1 AS X) AS [SingleRowTable1]
                           UNION ALL


                           SELECT 1 AS [C1]
                           FROM   (SELECT 1 AS X) AS [SingleRowTable2]) AS [UnionAll1]) AS [Project3]
ORDER  BY [Project3].[SearchType] ASC,
          [Project3].[C2] ASC

不幸的是,我在 SQL 方面的经验有限,光是看着就头疼,但显然有些事情搞混了。

有人能指出sql查询中的问题出在哪里吗?

按我的意愿期望这是否合理?是否可以将其视为一个错误,或者只是我的期望在合同中不支持 LINQ 应该如何工作?

更新

等等,为什么我不直接查看 SQL 查询的输出?大脑以神秘的方式运作……

sql 查询返回这个:

[SearchType, C1, C2]
{Text, 1, Text}  
{Text, 1, 123}  
{Organization, 1, 123}  
{Organization, 1, Organization}  
{Subject, 1, Subject}  
{Subject, 1, 123}  

但是 .ToList() 之后的结果仍然只包含三个项目。这只会让我更加困惑,肯定是LINQ的一些隐含的内部行为会产生意想不到的后果?

【问题讨论】:

    标签: c# entity-framework linq-to-entities sql-server-2012 entity-framework-5


    【解决方案1】:

    很难相信名称和值的顺序在 JSON 对象中发生了翻转,但显然它确实发生了。

    这可能与List&lt;T&gt; 中的项目顺序永远不能保证等于插入顺序有关。您可以通过完全不使用列表来防止此问题:

    var result = MyEntities.Instance.SearchStatistics
        .GroupBy(x => x.SearchType)
        .Select(y => new { y.Key, Count = y.Count() })
        .ToList();
    
    return Json(new
    {
        Text = result.First(x => x.Key == "Text").Count.ToString(),
        Organization = result.First(x => Key) == "Organization").Count.ToString(),
        Subject = result.First(x => x.Key == "Subject").Count.ToString(),
    }, JsonRequestBehavior.AllowGet);
    

    【讨论】:

    • 感谢您提供替代解决方案,但是,“这可能与 List 中的项目顺序永远不能保证等于插入顺序有关。”不就是这样吗? stackoverflow.com/questions/1043039/…
    • 我猜你是对的,尽管它没有记录在案 (stackoverflow.com/a/1790265/861716)。但是,如果不是,Sort 方法的意义何在?但我无法真正解释您的代码中发生了什么。
    • 但是看到您的更新,我想我仍然会寻求一种解决方案,它可以使数据库查询保持简单并在内存中进行转换。 EF 尝试将 LINQ 表达式中的 everything 转换为 SQL,因此转换和创建列表会造成很多混乱。此外,SQL 结果集并不总是反映 EF 查询的最终结果,因为 EF 可能会在其后处理中过滤结果(虽然仍然没有解释任何内容,但至少 SQL 会更干净,因此更容易检查它)。
    • 是的,我肯定会使用您的匿名类型的解决方案,更简洁,生成的 SQL 更简单,并且它实际上产生了您期望的结果。知道这个问题的原因仍然很有趣......
    猜你喜欢
    • 2013-06-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-03
    • 2016-09-07
    • 1970-01-01
    • 1970-01-01
    • 2016-05-02
    相关资源
    最近更新 更多