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).
x => x.Messageif you are after a list of strings instead of a list of objects all containing only a string.orderbybefore applyingtake