6

我正在使用实体框架从 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

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

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

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

编辑:第四条语句只是颠倒了GroupByandToArray方法链接的顺序。做出这个小小的改变,我得到了我期望的行数,但真正的问题是这个问题无法以这种方式解决,因为真正的问题是代码将来自这个 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 框架中的任何类型的字符串比较,但问题仍然存在。

4

2 回答 2

5

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

特别是关于整理。

于 2014-02-07T16:28:15.430 回答
2

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

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

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

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

于 2014-02-13T02:46:49.340 回答