Я извлекаю некоторые данные из SQL с помощью Entity Framework.Почему LINQ GroupBy производит разные результаты, когда предшествует ToArray()?
Я написал код, который выглядит как фрагмент ниже. Обратите внимание, что Something
- это значение varchar
из базы данных. Более того, я думаю, что может быть уместно, что каждое значение в Something
состоит из десяти цифр, дефиса, а затем еще двух цифр, например «-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
. Обычно я делаю это, когда ожидаю, что код вызова будет использовать всю информацию и не хочет иметь дело с любыми Lazy Loading SNAFU. Однако, когда я запускаю этот код в отладчике, этот третий оператор дает 5727 групп, 123 меньше, чем я ожидаю.
Edit: Четвертый оператор просто меняет порядок GroupBy
и ToArray
метод построения цепочки. Сделав это небольшое изменение, я получаю количество строк, которые я ожидаю, но реальная проблема, что этот вопрос не может быть решён таким образом, потому что в реальной проблеме есть код, который связывает данные из этого SQL-вызова с другими данными и возвращает их в одном объекте ,
Я хочу понять, как это происходит, поскольку использование ToArray
заставляет меня получить неправильное количество результатов.
Последующие меры: В ответ на ответ user995219, я переписал MyView
так, что он имеет дополнительный столбец: SomethingInt
, который просто containins 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 из изображения, но проблема сохраняется.
имеет третий счетчик правильного счета перед GroupBy? группе по требованию IEqualityComparer для abjects, когда делаете это в памяти, однако ваша группа по ключу является примитивным типом, тогда как вы имеете дело с entityframework, можете ли вы ответить на это: [что такое 'EdmFunctions' для?] (http://stackoverflow.com/questions/21607456/what-are-edmfunctions-for) –
Я отредактировал свое сообщение, чтобы уточнить, что 'Something', который я группирую, является' varchar' в SQL. И мне очень жаль, но я не знаю ответа на вопрос, на который вы ссылаетесь. –
Я бы сказал, что когда group by выполняется без toarray, он преобразуется в выражение sql. Когда вы применяете группу toarray, выполняется по свойству объекта. Поэтому, если вы сначала выполнили код и сделали некоторую дополнительную работу, например, обрезную строку, данные можно было сгруппировать больше. Пожалуйста, +1 для моей фантазии. – sam