Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is Guid.ToString returning capitalised string in Linq?

Tags:

c#

.net

I have encountered some weird/unexpected behaviour in which Guid.ToString() in a Linq expression returns a different result than Guid.ToString() in a foreach loop.

What the method is doing:

The method in question is simply taking an object and then creates a new view-model from the original object. The company I work for has decided that Guid's will not be allowed on view-models, due to one of our older JSON serializers having an bug in which Guid's were not serialized correctly.

The problem/unexpected result:

While debugging/testing my method I found that the Linq expression I created was returning a strange result. When converting my Guid to its string representation, the result was being automatically capitalised. I didn't believe that it was the Linq expression at first but once I had converted the logic into a foreach loop I got a lower-cased string representation of my Guid.

Example code:

Please note that the property types for lookupList (ID1, ID2, ID3) are all of type Guid and the properties on NewClass are all of type string.

Linq expression:

List<NewClass> returnList = lookupList.Select(i => new NewClass {
                   Property1 = i.ID1.ToString(),
                   Property2 = i.ID2.ToString(),
                   Property3 = i.ID3.ToString(),
                   .....
                }).ToList();

Returns:

{
    Property1=7081C549-64D6-458E-A693-0D2C9C47D183
    Property2=06DD6A59-D339-4E15-89EA-48803DBA271E
    Property3=9A876EDD-3B79-C27E-1680-E0820A0CD6EC
}

Foreach loop:

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(),
        .....
    });
}

Returns:

{
    Property1=7081c549-64d6-458e-a693-0d2c9c47d183
    Property2=06dd6a59-d339-4e15-89ea-48803dba271e
    Property3=9a876edd-3b79-c27e-1680-e0820a0cd6ec
}

The question:

Why is this happening and is this expected behaviour? I would expect both the Linq expression and the foreach loop to return the same result when .ToString() is applied to my Guid but somehow it is not. I have also checked that there are no .ToString() overrides in either class.

Thank you in advance.

Update:

The lookupList has been handled by a .ToList() before it hits my method. LookupList is of type List<t> where t is a custom business entity which has additional properties that the database does not have. Apologies, I did not make this clear in my original question.

like image 637
Mr Hickle Avatar asked Jul 09 '15 08:07

Mr Hickle


1 Answers

If lookupList is a IQueryable object, so that you are using LINQ to SQL, and not LINQ to object, then the two queries are not the same.

lookupList.Select(i => new NewClass { Property1 = i.ID1.ToString(), etc..

Will perform a SQL SELECT, the result will depend on your DBMS. My guess is that the ToString will be translate to something like CAST(Property1, varchar)

Whereas this query:

foreach (var item in lookupList)
{
    returnList.Add(new NewClass { Property1 = item.ID1.ToString(), etc..

will first does a select in your database, and then calling ToString on it. So the method triggered is the ToString method of the C# object GUID.

Try this for example :

List<NewClass> returnList = lookupList.ToList().Select(i => new NewClass {
               Property1 = i.ID1.ToString(),
               Property2 = i.ID2.ToString(),
               Property3 = i.ID3.ToString(),
               .....
            }).ToList();

This should return lowercase Properties.

The .ToString is not normally support in SQL, and the first query should exception. But my guess it that someone in your team read that blog post that explain how you can create a SQL function that will map an Entity Framework call.

Interesting fact : the example function create uppercase Guid strings.

EDIT : In pure LINQ to Object, this code return lowercase strings:

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();

We need more infos on lookupList object and those properties IDx. Are they pure C# Guid object?

You said that you already .ToListed your object. That will not work if your are doing it the wrong way :

BAD:

lookupList.ToList();
var returnList = lookupList.Select(i => new NewClass {

GOOD:

var purePOCOList = lookupList.ToList();
var returnList = purePOCOList.Select(i => new NewClass {
like image 113
Cyril Gandon Avatar answered Nov 14 '22 13:11

Cyril Gandon