C# 检索数据,奇怪的行为
我正在使用EF6从SQLServer检索一些数据。我以前遇到过这个问题,但我没有问过任何人 对于下面的代码,只需关注select 假设在数据库中我有两行:C# 检索数据,奇怪的行为,c#,entity-framework,linq,C#,Entity Framework,Linq,我正在使用EF6从SQLServer检索一些数据。我以前遇到过这个问题,但我没有问过任何人 对于下面的代码,只需关注select 假设在数据库中我有两行: 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.M
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();
第二个列表是相反的
如果我有更多的行,情况是一样的:第一行是ok,第二行是reversed,第三行是ok,第四行是reversed,依此类推
如果我将代码更改为:
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();
var results=db.Table.Where(o=>o.Version==1.ToList();
var x=结果。选择(o=>新列表{o.M01,o.M02,o.M03,o.M04,o.M05});
返回x.ToList();
这里一切都会好起来的
如果我在EF查询中创建列表,似乎有问题
我错过了什么重要的事情吗
更新
添加一些屏幕截图:
TL;DR
新列表{o.M01,o.M02,o.M03,o.M04,o.M05}.OrderBy(p=>p).ToList()
正如@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 });
正如您在ORDERBY子句中看到的,查询按[Project6].[C2]排序,这只是一个返回1的控制标志。
这是因为,正如@marc_在注释中指定的那样,您没有明确指定结果的顺序
如果你想改为使用一些东西,比如:
风险值结果=
其中(o=>o.Version==1)
.Select(o=>newlist{o.M01,o.M02,o.M03,o.M04,o.M05}.OrderBy(p=>p.ToList())
。。。然后生成的SQL将包含正确的order子句,您将得到EXEPCED结果。
var结果=
其中(o=>o.Version==1)
.选择(o=>new{M01=o.M01,M02=o.M02,M03=o.M03,M04=o.M04,M05=o.M05});
返回结果。选择(o=>newlist{o.M01,o.M02,o.M03,o.M04,o.M05});
。。。这样,您就不必费心处理生成的SQL顺序,并且可以控制列在输出列表上返回的顺序。这是EF从一个数据库记录中生成的值具体化
列表
对象的方式中的一个可重现的小故障。结果表明,执行的SQL语句以这种意外的交替顺序返回值。这意味着EF生成的SQL查询永远不能保证返回特定的顺序。但是,由于SQL是一种基于集合的语言,它从来没有保证集合中元素的顺序。可以生成一个对元素进行正确排序的查询SQL,但我认为EF从未预料到您的(不太常见)场景,或者认为不值得为其提供支持
因为它是EF源代码的一部分,所以没有快速修复它的方法,您必须解决您的工作。您可能需要提交一份bug报告
IMO的根本问题是糟糕的数据规范化。如果您的表是由
M
记录组成的表的父级,每个记录代表一个双值,可能带有一个序列字段,那么获得这个列表就容易多了。以及在这两种情况下生成的sql查询是什么样子的?因为您没有明确要求任何特定的顺序,而且您反对sql Server,未定义返回值的顺序-SQL Server可以按照其可能选择的任何顺序自由返回值。如果需要排序,则必须使用EF中的.OrderBy
或T-SQLT中的ORDER BY
明确定义,但M01、M02、M03、M04、M05是表的列。EF如何映射第一行:M01=1,M02=2,M03=3,M04=4,M05=5,第二行:M01=10,M02=9,M03=8,M04=7,M05=6?按顺序排序就是对结果排序。我的问题是错误地映射一行的列,而不是结果的顺序。也许我不清楚。稍后我将发布一些截图,以便更具体。@BogdanC。您正在将结果映射到列表。EF的映射没有问题,但就您使用它所做的工作而言,如果您要将结果映射到(比如)一个具有所需五个支柱的新类,您就不会有SQL返回添加到列表中的任意有序结果集的问题。尝试执行类似于Select(o=>new{M01=o.M01,M02=o.M02,M03=o.M03,M04=o.M04,M05=o.M05})的操作代码>看看我在说什么。@bogdance。顺便说一句,你试过我建议的解决方案吗?我相信它会解决您的问题……这只是根据列表的值对列表进行排序,它不会重建Mxx
字段的顺序。SQL语句(不含OrderBy
)按正确顺序返回值。“是EF把他们搞得一团糟。”格塔诺尔说得对。我的解决方案错了,你说得对。不过,查询并没有按正确的顺序返回结果。在EF上重新编程他的场景,并对DB执行内部查询以检查它。
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 });
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
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 });