传统上,当我尝试从数据库中获取用户数据时,我使用了以下方法(在某种程度上):
DbUsers curUser = context.DbUsers.FirstOrDefault(x => x.u_LoginName == id);
string name = curUser.u_Name;
string email = curUser.u_Email;
你可以看到我想做的就是获取名称和电子邮件,但在我看来,这个LINQ查询正在将所有存储在该用户的数据库中,并将其恢复,然后让我得到我想要的东西。
我一直在做一些研究,并找到了以下替代方案:
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
}
如果有的话哪个更好?当我只想检索一些结果/数据时,是否有更轻松的方法?
答案 0 :(得分:61)
如果您只想获得两个字段,那么您应该在执行查询之前投影您的实体(在这种情况下,当您调用FirstOrDefault
时查询会被执行)。使用Select
运算符投影到具有必填字段的匿名对象:
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;
这将产生如下的SQL:
SELECT TOP 1 u_Name, u_Email FROM DbUsers
WHERE u_LoginName = @id
在第二种情况下,您在执行查询之前进行投影(即枚举开始)。这就是为什么只加载必填字段的原因。但查询会略有不同(没有TOP 1
)。实际上,如果您将第二种方法转换为lambda语法,它将几乎相同:
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
}
只是为了显示完整的图片,没有投影,你会得到第一个找到用户的所有字段:
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;
在这种情况下,在执行查询之前不会投影用户实体,并且您将获得从数据库加载并映射到用户实体的所有用户字段:
SELECT TOP 1 u_LoginName, u_Name, u_Email /* etc */ FROM DbUsers
WHERE u_LoginName = @id
答案 1 :(得分:8)
第二个更好。您只能从数据库中获取所需的数据,以便网络流量更轻。
扩展方法可以获得相同的结果:
var user = context.DbUsers
.Where(x => x.u_LoginName == id)
.Select(x => new {...})
.FirstOrDefault();
答案 2 :(得分:1)
如果您不需要整个实体,但需要一些值,那么请使用new {name = s.u_Name, email = s.u_Email}
。因为,这个物体对于制造来说“更轻”。
当你使用FirstOrDefault获取实体时,它'保存在DBContext中,但是你没有对它做任何事情。
所以,我建议你只获得你需要的数据。