LINQ to Entities的意外行为,可能是错误?

时间:2014-06-10 06:31:07

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

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

问题
我想在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();

现在,只有在DB

中执行分组查询时,它才能正常工作

将生成的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的一些隐含的内部行为会产生意想不到的后果吗?

1 个答案:

答案 0 :(得分:1)

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

这可能与List<T>中的项目顺序永远不会保证等于广告订单的事实有关。您可以完全不使用列表来阻止此问题:

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);