为什么LINQ GroupBy在ToArray()之前会产生不同的结果?

Dan*_*don 6 .net linq entity-framework group-by toarray

我正在使用Entity Framework从SQL中提取一些数据.

我写了一些看起来像下面的代码片段的代码.请注意,这Somethingvarchar数据库中的值.此外,我认为每个值Something包含十个数字,连字符,然后两个以上的数字可能是相关的,例如"0123456789-01".(不要提醒我这是糟糕的设计;我不是这个数据库的架构师.)

var X = Entities.MyView
    .Select(x => x.Something)
    .Distinct();
// 5850 elements

var Y = Entities.MyView
    .GroupBy(x => x.Something);
// 5850 elements

var Z = Entities.MyView
    .ToArray()
    .GroupBy(x => x.Something);
// 5727 elements

// Added in response to user995219's Answer
var ZZ = Entities.MyView
    .GroupBy(x => x.Something)
    .ToArray();
    // 5850 elements
Run Code Online (Sandbox Code Playgroud)

第一个语句Something从视图中下拉列的不同值MyView.它得到了结果5850元素,这是我所期望的.

第二个语句将整个视图拉下来并按唯一值对其进行Something分组,产生5850个分组,这正是我所期望的.

第三个语句完全相同,只是它调用ToArray了来自的值MyView.通常,当我希望调用代码使用整个数据并且不想处理任何延迟加载SNAFU时,我会这样做.但是,当我在调试器中运行此代码时,此第三个语句产生5727个分组,比我预期的少123个.

编辑:第四语句只是反转的顺序GroupByToArray方法链接.做这个小改动,我得到了我期望的行数,但是这个问题无法通过这种方式解决的真正问题是因为真正的问题是将来自此SQL调用的数据与其他数据相关联并将它们返回到单个对象中的代码.

我希望了解使用是如何ToArray导致我获得错误数量的结果.

后续:为了响应user995219的回答,我重写MyView了它,以便它有一个额外的列:SomethingInt,它只包含一个32位整数,通过省略连字符Something并将结果视为一个整数形成.然后,LINQ代码执行GroupBy新建的整数.

然而,即使有这种变化,我仍然遇到同样的问题.

var A = Entities.MyView
    .ToArray();
// Returns 17893 elements, the same as if I ran SELECT * FROM MyView

var array0 = A.Select(x => x.SomethingInt).Distinct();
// Returns 5727 elements when I expect 5850
Run Code Online (Sandbox Code Playgroud)

在SQL中,SELECT COUNT(DISTINCT(SomethingInt)) FROM MyView;返回5850,正如我所料.

这应该在.net框架中进行任何类型的字符串比较,但问题仍然存在.

小智 5

ToArray语句执行查询,并使用字符串相等比较器在内存中执行group by.前两个语句在SQL级别执行组.有区别: String和T-SQL之间的字符串比较差异?

特别是关于整理.


Dan*_*don 2

我找到了答案。user995219的答案很有用,但不是完整的解释。

显然,LINQ 方法会检查它们正在操作的内容。就我而言,我使用实体框架生成的类。它们具有“实体键”,允许 .net 框架区分具有相同内容的两行和同一行的两个实例。

就我而言,我使用的是复杂的视图,.net 框架错误地推断了实体键,然后丢弃了行,因为它认为它们是相同的。

我的解决方案是修改我的视图,以便有一个唯一标识每一行的 GUID,并将 GUID 用作实体键。