c# - tutorial - `from..where` or` FirstOrDefault` en LINQ
sql command entity framework (3)
Tradicionalmente, cuando traté de obtener datos para un usuario de una base de datos, y he utilizado el siguiente método (hasta cierto punto):
DbUsers curUser = context.DbUsers.FirstOrDefault(x => x.u_LoginName == id);
string name = curUser.u_Name;
string email = curUser.u_Email;
Puedes ver que todo lo que quiero hacer es obtener el nombre y el correo electrónico, pero me parece que esta consulta LINQ está almacenando todo en la base de datos de ese usuario, trayéndolo de vuelta y luego obteniéndolo.
He estado investigando y he encontrado la siguiente alternativa:
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
}
¿Cuál sería mejor, si es que hay alguno? ¿Hay algún método más ligero para usar cuando solo quiero recuperar algunos resultados / datos?
El segundo es mejor. Solo obtiene los datos necesarios de la base de datos por lo que el tráfico de la red es más ligero.
Puede obtener el mismo resultado con los métodos de extensión:
var user = context.DbUsers
.Where(x => x.u_LoginName == id)
.Select(x => new {...})
.FirstOrDefault();
Si desea obtener solo dos campos, entonces debe proyectar su entidad antes de que se ejecute la consulta (y en este caso, la consulta se ejecuta cuando llama a FirstOrDefault
). Use el operador Select
para proyección a un objeto anónimo con los campos obligatorios:
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;
Eso generará SQL como:
SELECT TOP 1 u_Name, u_Email FROM DbUsers
WHERE u_LoginName = @id
En el segundo caso, usted está haciendo una proyección antes de que se ejecute la consulta (es decir, la enumeración comenzada). Es por eso que solo se cargan los campos obligatorios. Pero la consulta será ligeramente diferente (sin TOP 1
). En realidad, si va a convertir el segundo enfoque a la sintaxis lambda, será casi el mismo:
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
}
Y solo para mostrar una imagen completa, sin proyección obtienes todos los campos del primer usuario encontrado:
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;
En ese caso, la entidad de usuario no se proyecta antes de que se ejecute la consulta y obtendrá todos los campos del usuario cargados desde la base de datos y asignados a la entidad de usuario:
SELECT TOP 1 u_LoginName, u_Name, u_Email /* etc */ FROM DbUsers
WHERE u_LoginName = @id
Si no necesita una entidad completa, pero sí algunos valores, use la new {name = s.u_Name, email = s.u_Email}
. Porque, este objeto es mucho más "ligero" para la cunstrucción. Cuando obtiene la entidad con FirstOrDefault, se guarda en DBContext, pero no hace nada con él. Entonces, te aconsejo que obtengas solo los datos que necesitas.