45 votes

`from..where` ou` FirstOrDefault` dans LINQ

Traditionnellement, quand j'ai essayé de récupérer les données d'un utilisateur à partir d'une base de données, et j'ai utilisé la méthode suivante (à un certain degré):

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

Vous pouvez voir que tout ce que je veux faire est d'obtenir le Nom et l'e-Mail, mais il me semble que cette requête LINQ est arriver tout stocké dans la base de données de l'utilisateur, de le ramener, puis me permettre d'obtenir ce que je veux.

J'ai fait quelques recherches et ai trouvé l'alternative suivante:

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
}

Ce qui serait mieux, si tout? Est-il plus léger de la méthode à utiliser lorsque je souhaite récupérer quelques résultats / données?

63voto

Sergey Berezovskiy Points 102044

Si vous souhaitez obtenir seulement deux champs, alors vous devriez projet de votre entité avant la requête est exécutée (et dans ce cas, la requête est exécutée lorsque vous appelez FirstOrDefault). Utiliser Select de l'opérateur de projection pour objet anonyme avec les champs obligatoires:

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;

Que va générer le SQL comme:

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

Dans le second cas que vous faites de la projection avant de requête est exécutée (c'est à dire l'énumération commencé). C'est pourquoi seuls les champs obligatoires sont chargés. Mais la requête va être légèrement différente (sans TOP 1). En fait, si vous allez convertir deuxième approche pour le lambda de la syntaxe, il sera presque les mêmes:

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
}

Et juste pour montrer l'image est complète, sans projection, vous obtenez tous les domaines de premier utilisateur:

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;    

Dans ce cas, l'utilisateur de l'entité est pas prévu avant la requête est exécutée et vous obtiendrez tous les champs de l'utilisateur chargé à partir de la base de données et cartographiés à l'utilisateur de l'entité:

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

10voto

Cosmin Points 663

La seconde est meilleure. Vous n'obtenez que les données nécessaires de la base de données, ce qui réduit le trafic réseau.

Vous pouvez avoir le même résultat avec les méthodes d'extension:

 var user = context.DbUsers
                  .Where(x => x.u_LoginName == id)
                  .Select(x => new {...})
                  .FirstOrDefault();
 

1voto

Backs Points 267

Si vous n'avez pas besoin d'entité entière mais de valeurs, utilisez new {name = s.u_Name, email = s.u_Email} . Parce que cet objet est beaucoup plus "léger" pour la construction. Lorsque vous obtenez une entité avec FirstOrDefault, elle est enregistrée dans DBContext, mais vous ne faites rien avec. Je vous conseille donc de n'obtenir que les données dont vous avez besoin.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X