1

Help understand please why that query returns same values but if i use anonymous type it return correct result

//same values
var deviceMessageList1 = _deviceMessageRepository.Fromdevicemessages
                .Where(m => m.DeviceId == deviceId).Take(1000).ToList();
//different values
            var deviceMessageList2 = _deviceMessageRepository.Fromdevicemessages
                .Where(m => m.DeviceId == deviceId).Take(1000).Select(x=> new { Message = x.Message }).ToList();

[Sample]

3
  • 1
    You need to explain more, pretty much impossible to understand what you expect the result to be. btw you could do x => x.Message if you are after a list of strings instead of a list of objects all containing only a string. Commented Jul 6, 2017 at 7:33
  • try to sort the results by adding the orderby before applying take Commented Jul 6, 2017 at 7:34
  • Returns objects of class that describe the table public class fromdevicemessage { [Key] public int DeviceId { get; set; } public DateTime AddedDate { get; set; } public string Message { get; set; } public int ProtocolCommandId { get; set; } public int CounterId { get; set; } } Commented Jul 6, 2017 at 7:40

2 Answers 2

2

I've made a few assumptions:

  • I assume your entity class is called Fromdevicemessage
  • I assume that Message is a String property

.Select() in LINQ does not influence which items are retrieved. It only influences how the retrieved items are presented.
If you know SQL, you will see that SELECT in SQL works exactly the same (which is why the LINQ method is intentionally called Select, as it works the same, functionally speaking)

It helps if you understand the intention of every method, I'll comment it in:

var deviceMessageList1 =_deviceMessageRepository.Fromdevicemessages

     .Where(m => m.DeviceId == deviceId)  //Only return the items which have their DevicedId set to [deviceId]
     .Take(1000)                          //Give me the first 1000 items
     .ToList()                            //Make a list from these 1000 items

Notice that you have only specified which rows you want to retrieve. You have not specified how you want the output to be formatted.
By default, you will receive objects of the corresponding entity type Fromdevicemessage.

The list you see at the end is therefore a List<Fromdevicemessage>.


var deviceMessageList1 =_deviceMessageRepository.Fromdevicemessages

     .Where(m => m.DeviceId == deviceId)       //Only return the items which have their DevicedId set to [deviceId]
     .Take(1000)                               //Give me the first 1000 items
     .Select(x => x.Message)                   //For each retrieved item, instead of the item itself, only give me its Message (= string)
     .ToList()                                 //Make a list from these 1000 strings

Notice what the Select statement adds. It basically tells you that you do not want the full Fromdevicemessage object, but only want the Message property. You're basically telling the compiler the following:

For each Fromdevicemessage object that is currently retrieved, render me its Message property.

You were originally working with a collection of Fromdevicemessage objects. But the .Select() statement converted that collection into a collection of String objects.
Simplified, the Select() method converts every object in the source collection, based on your mapping (e.g. x => x.Message), and returns you the list of mapped values.

The list you see at the end is therefore a List<String>.


I cheated a little bit...

In case you hadn't noticed, I changed your Select statement.

Your version:

.Select( x => new { Message = x.Message } )

My version:

.Select( x => x.Message )

Both are valid code, but they work a bit differently.

  • Your version converts the retrieved items into anonymous objects. The resulting list will therefore be a list of anonymous objects.

  • My version converts the retrieved items into String objects. The resulting list will therefore be a list of strings.

There are cases where creating an anonymous type is useful. Most commonly, it is useful if you want to return multiple values (e.g. both the Message and Recipient properties).

However, your example only retrieves a single property. In this case, there is no benefit to using anonymous types. Using anonymous types when you want to retrieve a single property makes the code more complex for no good reason or benefit.
You are making yourself responsible for later unwrapping that anonymous type and reading its Message property.

It's easier to simply handle the strings directly, rather than wrapping them in an anonymous type. That means you have one less wrapped layer to worry about.


Update after your comment

Taking a closer look at the image you linked; is your question specifically why the debug values (when you hover over the results like you do in the picture) are different?

What you see in the little popup (before expanding) is essentially the .ToString() output of the variable you're inspecting.

The first example consists of a List<Fromdevicemessage>. Since Fromdevicemessage is a custom class you've built (and I assume you did not override its .ToString() method, the default ouput will be the name of the class, not its contents.

That's just how it works. If you override the .ToString() method in your Fromdevicemessage class, then you can change what it looks like.

public override string ToString()
{
     return $"Message : {this.Message}";
}

In the second example, you are dealing with a List of anonymous types. Anonymous types have a custom .ToString() method, which already shows you the content of the object rather than its classname (since anonymous objects have no classname, at least as far as a developer can see).

Sign up to request clarification or add additional context in comments.

2 Comments

thank you for open answer but it not answer in my question. In first case i have anonymous type where will several items including Message but problem is all this objects consists same values. The message in each item is same. From first to last. In second case if i will use the Select() method i'll get different values for simplysity i used only message in method Select() but if I will create anonymous type with all values i will take different values. Select() Somehow Influenced on query. Sorry fore my bad English.
@qqqqq: See an update to my answer. If this is still not the problem you are facing, you will need to improve your question as it seems many people are struggling to understand what you mean.
1

Both the queries are same except in second query you are using anonymous type. first query will return original object with all the properties in that object and second query will just return message as you are using anonymous type.

To better understand this is like //first query

select Top 1000 * from Fromdevicemessages 

//Second query

select Top 1000 Message from Fromdevicemessages 

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.