我正在使用 Entity Framework 从 SQL 中提取一些数据。
我写了一些看起来像下面的代码片段的代码。请注意,Something
是来自数据库的 varchar
值。此外,我认为 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
第一条语句从
Something
View 中提取 MyView
列的不同值。它为我提供了结果 5850 个元素,这正是我所期望的。第二个语句拉下整个 View 并按
Something
的唯一值对其进行分组,产生 5850 个分组,这正是我所期望的。第三个语句完全相同,除了它对
ToArray
中的值调用 MyView
。通常,当我希望调用代码使用全部数据并且不想处理任何延迟加载 SNAFU 时,我会这样做。但是,当我在调试器中运行此代码时,这第三个语句产生 5727 个分组,比我预期的少 123 个。编辑:第四条语句只是颠倒了
GroupBy
和 ToArray
方法链的顺序。进行这个小改动,我得到了我期望的行数,但真正的问题是这个问题不能用这种方式解决,因为真正的问题有代码将来自这个 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
在 SQL 中,
SELECT COUNT(DISTINCT(SomethingInt)) FROM MyView;
返回 5850,正如我所料。这应该消除 .net 框架中的任何类型的字符串比较,但问题仍然存在。
最佳答案
ToArray 语句执行查询,并使用字符串相等比较器在内存中执行 group by。
前两个语句在 SQL 级别执行 group by。
有区别:
String Comparison differences between .NET and T-SQL?
特别是关于整理。
关于.net - 为什么 LINQ GroupBy 在 ToArray() 之前会产生不同的结果?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21617733/