我使用EF 6从SQL Server检索一些数据。我过去遇到过这个问题,但我还没有问过任何人。
对于以下代码,只需关注选择。
让我们在数据库中说我有两行:
1 2 3 4 5
6 7 8 9 10
我的代码:
var results = db.Table.Where(o => o.Version == 1)
.Select(o => new List<double?>{ o.M01, o.M02, o.M03, o.M04, o.M05});
return results.ToList();
上面的代码将返回一个包含以下内容的列表列表:
previousDemand[0] = 1 2 3 4 5
previousDemand[1] = 10 9 8 7 6
第二个清单是相反的。
如果我有更多行,则会发生相同的情况:第一次正常,第二次反转,第三次正常,第四次反转等等。
如果我将代码更改为:
var results = db.Table.Where(o => o.Version == 1).ToList();
var x = results.Select(o => new List<double?>{ o.M01, o.M02, o.M03, o.M04, o.M05});
return x.ToList();
一切都会好起来的。
如果我在EF查询中创建列表似乎存在问题。
我错过了重要的事情吗?
答案 0 :(得分:4)
<强> TL; DR 强>
new List<double?> { o.M01, o.M02, o.M03, o.M04, o.M05 }.OrderBy(p => p).ToList()
sugest只对您提供的示例有效,但不能解决您的问题,正如@GertArnold在评论中指出的那样。
您可以做的不是查询列表,而是返回一个包含所需列的新实体。在实现结果后,您可以将其转换为列表。
var results =
db.Entities.Where(o => o.Version == 1)
.Select(o => new { M01 = o.M01, M02 = o.M02, M03 = o.M03, M04 = o.M04, M05 = o.M05 });
return results.Select(o => new List<double?> { o.M01, o.M02, o.M03, o.M04, o.M05 });
现在推理:
您的EF查询生成以下(非常混乱)SQL语句:
SELECT
[Project6].[Id] AS [Id],
[Project6].[C2] AS [C1],
[Project6].[C1] AS [C2]
FROM (
SELECT
CASE
WHEN ([UnionAll4].[C1] = 0) THEN [Extent1].[M01]
WHEN ([UnionAll4].[C1] = 1) THEN [Extent1].[M02]
WHEN ([UnionAll4].[C1] = 2) THEN [Extent1].[M03]
WHEN ([UnionAll4].[C1] = 3) THEN [Extent1].[M04]
ELSE [Extent1].[M05] END AS [C1],
[Extent1].[Id] AS [Id],
1 AS [C2]
FROM [dbo].[Entities] AS [Extent1]
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]
UNION ALL
SELECT 2 AS [C1]
FROM ( SELECT 1 AS X ) AS [SingleRowTable3]
UNION ALL
SELECT 3 AS [C1]
FROM ( SELECT 1 AS X ) AS [SingleRowTable4]
UNION ALL
SELECT 4 AS [C1]
FROM ( SELECT 1 AS X ) AS [SingleRowTable5]
) AS [UnionAll4]
WHERE 1 = [Extent1].[Version]
) AS [Project6]
ORDER BY [Project6].[Id] ASC, [Project6].[C2] ASC
正如您在ORDER BY子句中看到的那样,查询按[Project6]。[C2]排序,它只是一个返回1的控制标志。 这是因为,作为评论中指定的@marc_s,您没有明确指定结果的订单。
如果你想改为使用像:
那样
var results =
db.Entities.Where(o =&gt; o.Version == 1)
。选择(o =&gt;新列表{o.M01,o.M02,o.M03,o.M04,o.M05} .OrderBy(p =&gt; p).ToList()); < / p>
...然后生成的SQL将包含正确的order子句,您将获得exepcted结果。
var results =
db.Entities.Where(o => o.Version == 1)
.Select(o => new { M01 = o.M01, M02 = o.M02, M03 = o.M03, M04 = o.M04, M05 = o.M05 });
return results.Select(o => new List<double?> { o.M01, o.M02, o.M03, o.M04, o.M05 });
...那么您就不需要为生成的SQL顺序而烦恼,并且可以控制在输出列表中返回列的顺序。
答案 1 :(得分:2)
这是EF从源自一个数据库记录的值中实现List<T>
对象的方式中可重现的故障。事实证明,执行的SQL语句以此意外的交替顺序返回值。这意味着EF生成的SQL查询永远不能保证返回特定的订单。但由于SQL是一种基于集合的语言,因此它永远不会保证集合中元素的顺序。有可能生成一个正确排序元素的查询SQL,但我认为EF从未预料到你的(不那么常见)场景,或者认为值得努力支持它。
由于它是EF源代码的一部分,因此没有快速的方法来解决它,你必须解决你的解决方法。您可能想要提交错误报告。
根本问题IMO是错误的数据规范化。如果你的表是M
记录表的父表 - 每个表示一个双精度值,可能带有一个序列字段 - 那么获取这个列表列表会容易得多。