Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

`from..where` or `FirstOrDefault` in LINQ

Traditionally, when I've tried to get data for a user from a database, and I've used the following method (to some degree):

DbUsers curUser = context.DbUsers.FirstOrDefault(x => x.u_LoginName == id); string name = curUser.u_Name; string email = curUser.u_Email; 

You can see that all I want to do is get the Name and Email, but it seems to me that this LINQ query is getting everything stored in the database of that user, bringing it back, then allowing me to get what I want.

I have been doing some research and have found the following alternative:

var current = from s in context.DbUsers where s.u_LoginName == id select new {              name = s.u_Name,               email = s.u_Email            }; foreach (var user in current) {     //Stuff Here } 

Which would be better, if any at all? Is there a lighter method to use when I only want to retrieve a few results / data?

like image 863
TheGeekZn Avatar asked Jan 17 '14 13:01

TheGeekZn


People also ask

What is the use of FirstOrDefault in LINQ?

Use the FirstorDefault() method to return the first element of a sequence or a default value if element isn't there. List<double> val = new List<double> { }; Now, we cannot display the first element, since it is an empty collection. For that, use the FirstorDefault() method to display the default value.

What is the difference between where first and FirstOrDefault?

The major difference between First and FirstOrDefault is that First() will throw an exception if there is no result data for the supplied criteria whereas FirstOrDefault() will return the default value (null) if there is no result data.

What is first and FirstOrDefault in LINQ?

FirstOrDefault works same as First() does, FirstOrDefault returns the first element from a sequence, but here there is an advantage over First(), so if there is no record in the collection which matches input criteria then FirstOrDefault() can handle null values and it does not throw an exception. Conclusion.

Which is faster find or FirstOrDefault?

Find() runs almost as twice as faster, hoping . Net team will not mark it Obsolete in the future. Try timing Find() before FirstOrDefault .


2 Answers

If you want to get only two fields, then you should project your entity before query gets executed (and in this case query gets executed when you call FirstOrDefault). Use Select operator for projection to anonymous object with required fields:

var user = context.DbUsers                   .Where(u => u.u_LoginName == id)                   .Select(u => new { u.u_Name, u.u_Email })                   .FirstOrDefault(); // query is executed here  string name = user.u_Name; // user is anonymous object string email = user.u_Email; 

That will generate SQL like:

 SELECT TOP 1 u_Name, u_Email FROM DbUsers  WHERE u_LoginName = @id 

In second case you are doing projection before query gets executed (i.e. enumeration started). That's why only required fields are loaded. But query will be slightly different (without TOP 1). Actually if you will convert second approach to lambda syntax, it will be almost same:

var query = context.DbUsers                    .Where(u => u.u_LoginName == id)                    .Select(u => new { u.u_Name, u.u_Email });   // query is defined but not executed yet foreach (var user in query) // executed now {    //Stuff Here } 

And just to show complete picture, without projection you get all fields of first found user:

DbUsers user = context.DbUsers                       .Where(u => u.u_LoginName == id)                       .FirstOrDefault(); // query is executed here  string name = user.u_Name; // user is DbUsers entity with all fields mapped string email = user.u_Email;     

In that case user entity is not projected before query is executed and you'll get all fields of user loaded from database and mapped to user entity:

 SELECT TOP 1 u_LoginName, u_Name, u_Email /* etc */ FROM DbUsers  WHERE u_LoginName = @id 
like image 55
Sergey Berezovskiy Avatar answered Sep 20 '22 09:09

Sergey Berezovskiy


The second is better. You only get the needed data from database so the network traffic is lighter.

You can have the same result with extension methods:

var user = context.DbUsers                   .Where(x => x.u_LoginName == id)                   .Select(x => new {...})                   .FirstOrDefault(); 
like image 28
Cosmin Vană Avatar answered Sep 19 '22 09:09

Cosmin Vană