Вы должны знать о разнице между объектом, который реализует IQueryable
, и объектом, который реализует IEnumerable
.
. IEnumerable
представляет последовательность похожих элементов. Вы можете получить первый элемент последовательности, и как только вы получите такой элемент, вы можете получить следующий элемент.
Обычно это делается с помощью методов foreach или LINQ, таких как ToList (), Count ( ) Any (), FirstOrDefault () и т. Д. c. В глубине души все они используют GetEnumerator () и MoveNext () / Current.
С другой стороны, объект, который реализует IQueryable
, представляет потенциал для создания объекта IEnumerable . Он не представляет сам объект IEnumerable.
* IQueryable
содержит Expression
и Provider
. Expression
- это обобщенная форма c того, что должно быть запрошено. Provider
знает, кто должен выполнить запрос (обычно это система управления базами данных) и на каком языке использует эта СУБД (обычно SQL).
Как только вы начнете перечислять IQueryable
(GetEnumerator), Expression
отправляется Provider
, который переведет Expression
в SQL и попросит СУБД выполнить запрос. Возвращенные данные представлены как IEnumerator
, поэтому вы можете вызвать MoveNext / Current.
Какое отношение это имеет к моей проблеме?
Проблема в том, что Поставщик должен знать, как перевести ваше выражение в SQL. Хотя он довольно умен в переводе выражений, его функциональность ограничена. Он не знает ваших собственных классов и методов; Поставщик не может перевести их на SQL. На самом деле есть несколько методов LINQ, которые не поддерживаются. См. Поддерживаемые и неподдерживаемые методы LINQ (LINQ to Entities) .
В вашем случае проблема заключается в том, что ваш провайдер не знает, как перевести ToString(CultureInfo.CurrentCulture)
в SQL. Он не знает класс CultureInfo
.
Так что я не могу вернуть свой JobsCount в виде строки?
Нет, вы не можете.
Обычно это не проблема, потому что не стоит помещать число в строку. Кроме того, все скажут, что JobsCount - это число, а не какой-то текст, это создаст проблемы пользователям вашего метода, если они захотят что-то сделать с возвращенным JobsCount, например, подсчитают среднее значение JobsCount в течение месяца.
Единственная причина для преобразования чисел в строки состоит в том, что люди не могут очень хорошо интерпретировать биты, они намного лучше интерпретируют текстовое представление компьютерных чисел.
Следовательно: правильная схема будет заключаться в том, что числа хранятся в целых, десятичных, двойных и т. д. c.
Непосредственно перед отображением они преобразуются в текстовое представление. То же самое, если для ввода пользователя: пользователь вводит некоторый текст. Это проверено на правильность и переведено в число. После этого остается номер. Преимущество заключается в том, что вы уверены, что после преобразования его в число вам больше никогда не придется проверять правильность формата.
Кроме того: числа для компьютеров гораздо эффективнее, чем строки.
Итак, мой совет: сохраните его в виде числа и преобразуйте его в текст только тогда, когда вам необходимо: отобразить его, сохранить в текстовом файле (json, xml), чтобы общаться через inte rnet et c. Попробуйте выполнить преобразование как можно позже.
Но я не могу изменить свой класс, я должен преобразовать его в строку!
Ну, в этом case: получить ваши данные как число и использовать AsEnumerable()
. Это переместит ваш номер в локальный процесс. Там вы можете конвертировать свой номер, используя любой локальный код, который вы хотите.
var result = this._context.Clients.GroupJoin((client, jobsForThisClient) => new
{
Id = client.Id,
ClientNo = client.ClientNo,
...
JobsCount = jobsForThisClient.Count(),
})
// Execute the query and move the fetched data to local process
AsEnumerable()
// put the fetched data in a ClientIndexDto
.Select(fetchedData => new ClientIndexDto
{
Id = fetchedData .Id,
ClientNo = fetchedData .ClientNo,
...
JobsCount = fetchedData.JobsCount.ToString(CultureInfo.CurrentCulture),
});
Это не менее эффективно. На самом деле: это может быть даже более эффективно, поскольку ваш JobsCount передается как Int32: только четыре байта. Большинство текстовых представлений JobsCount занимает более четырех байтов.
Не забудьте поразить дизайнера, который думал, что JobsCount - это кусок текста.