C# 检索数据,奇怪的行为

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

我正在使用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.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 });