Почему Guid.ToString возвращает заглавную строку в Linq?
Я столкнулся с каким-то странным/неожиданным поведением, в котором Guid.ToString()
в выражении Linq возвращает другой результат, чем Guid.ToString()
в цикле foreach.
Что делает этот метод:
Этот метод просто берет объект, а затем создает новую модель представления из исходного объекта. Компания, с которой я работаю, решила, что Guid не будет разрешено на моделях просмотра, из-за того, что один из наших старших сериализаторов JSON имеет ошибку, в которой Guid не был правильно сериализован.
Проблема/неожиданный результат:
Во время отладки/тестирования моего метода я обнаружил, что выражение Linq, которое я создал, возвращало странный результат. При преобразовании моего Guid в его строковое представление результат автоматически заглавился. Я не верил, что это было выражение Linq вначале, но как только я преобразовал логику в цикл foreach, я получил строковое представление с нижним овалом моего Guid.
Пример кода:
Обратите внимание, что типы свойств для lookupList (ID1, ID2, ID3) являются типами Guid, а свойства в NewClass - это строка типа.
Выражение Linq:
List<NewClass> returnList = lookupList.Select(i => new NewClass {
Property1 = i.ID1.ToString(),
Property2 = i.ID2.ToString(),
Property3 = i.ID3.ToString(),
.....
}).ToList();
Возврат:
{
Property1=7081C549-64D6-458E-A693-0D2C9C47D183
Property2=06DD6A59-D339-4E15-89EA-48803DBA271E
Property3=9A876EDD-3B79-C27E-1680-E0820A0CD6EC
}
Цикл Foreach:
var returnList = new List<NewClass>();
foreach (var item in lookupList)
{
returnList.Add(new NewClass
{
Property1 = item.ID1.ToString(),
Property2 = item.ID2.ToString(),
Property3 = item.ID3.ToString(),
.....
});
}
Возврат:
{
Property1=7081C549-64D6-458E-A693-0D2C9C47D183
Property2=06DD6A59-D339-4E15-89EA-48803DBA271E
Property3=9A876EDD-3B79-C27E-1680-E0820A0CD6EC
}
Вопрос:
Почему это происходит и является ли это ожидаемым поведением? Я бы ожидал, что выражение Linq и цикл foreach вернут тот же результат, когда .ToString()
применяется к моему Guid, но так или иначе это не так. Я также проверил, что нет переопределений .ToString()
в любом классе.
Спасибо заранее.
Update:
lookupList
обрабатывается .ToList()
до того, как он ударит мой метод. lookupList
имеет тип List<t>
, где t
- это настраиваемый бизнес-объект, который имеет дополнительные свойства, которых нет в базе данных. Извинения, я не сделал этого ясно в моем первоначальном вопросе.
Ответы
Ответ 1
Если lookupList
является объектом IQueryable, так что вы используете LINQ to SQL
, а не LINQ to object
, то два запроса не совпадают.
lookupList.Select(i => new NewClass { Property1 = i.ID1.ToString(), etc..
Выполняет SQL SELECT, результат будет зависеть от вашей СУБД. Я предполагаю, что ToString будет переводить на что-то вроде CAST(Property1, varchar)
В то время как этот запрос:
foreach (var item in lookupList)
{
returnList.Add(new NewClass { Property1 = item.ID1.ToString(), etc..
сначала сделает выбор в вашей базе данных, а затем вызовет ToString на нем. Таким образом, вызванный метод - это метод ToString объекта GUID объекта С#.
Попробуйте это, например:
List<NewClass> returnList = lookupList.ToList().Select(i => new NewClass {
Property1 = i.ID1.ToString(),
Property2 = i.ID2.ToString(),
Property3 = i.ID3.ToString(),
.....
}).ToList();
Это должно возвращать свойства нижнего регистра.
.ToString обычно не поддерживается SQL, и первый запрос должен быть исключением. Но я предполагаю, что кто-то из вашей команды прочитал сообщение в котором объясняется, как вы можете создать функцию SQL, которая будет отображать вызов Entity Framework.
Интересный факт: примерная функция создает строчные строковые строки Guid.
EDIT: в чистом LINQ to Object этот код возвращает строчные строки:
var lookupList = new[] { new Tuple<Guid, Guid>(Guid.NewGuid(), Guid.NewGuid()) };
var returnList = lookupList.Select(i => new
{
Property1 = i.Item1.ToString(),
Property2 = i.Item2.ToString(),
}).ToList();
Нам нужно больше информации об объекте lookupList
и те свойства IDx
. Являются ли они чистыми С# Guid object?
Ты сказал, что ты уже. Это не сработает, если вы делаете это неправильно:
BAD
lookupList.ToList();
var returnList = lookupList.Select(i => new NewClass {
ХОРОШО
var purePOCOList = lookupList.ToList();
var returnList = purePOCOList.Select(i => new NewClass {