LINQ中的`from..where`或`FirstOrDefault`

The*_*kZn 44 c# linq entity-framework

传统上,当我试图从数据库中获取用户的数据时,我已经使用了以下方法(在某种程度上):

DbUsers curUser = context.DbUsers.FirstOrDefault(x => x.u_LoginName == id);
string name = curUser.u_Name;
string email = curUser.u_Email;
Run Code Online (Sandbox Code Playgroud)

您可以看到我想要做的就是获取名称和电子邮件,但在我看来,这个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
}
Run Code Online (Sandbox Code Playgroud)

如果有的话哪个更好?当我只想检索一些结果/数据时,是否有更轻松的方法?

Ser*_*kiy 62

如果您只想获得两个字段,那么您应该在执行查询之前预测您的实体(在这种情况下,查询将在您调用时执行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;
Run Code Online (Sandbox Code Playgroud)

这会产生如下的SQL:

 SELECT TOP 1 u_Name, u_Email FROM DbUsers
 WHERE u_LoginName = @id
Run Code Online (Sandbox Code Playgroud)

在第二种情况下,您在执行查询之前进行投影(即枚举开始).这就是为什么只加载必填字段的原因.但查询会略有不同(没有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
}
Run Code Online (Sandbox Code Playgroud)

只是为了显示完整的图片,没有投影,您将获得第一个找到的用户的所有字段:

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;    
Run Code Online (Sandbox Code Playgroud)

在这种情况下,在执行查询之前不会投影用户实体,并且您将获得从数据库加载并映射到用户实体的所有用户字段:

 SELECT TOP 1 u_LoginName, u_Name, u_Email /* etc */ FROM DbUsers
 WHERE u_LoginName = @id
Run Code Online (Sandbox Code Playgroud)

  • 它突然间显得如此明显. (4认同)
  • 还值得一提的是,您可以将数据投影到单独的类型中.它不必是匿名类型=>`new MyType {Username = u.u_Name}` (4认同)
  • _"如果你只想获得两个字段,那么你应该在执行查询之前预测你的实体"_如果我选择匿名类型或完全初始化对象的两个属性,这真的很重要吗?后者的优点是我可以在任何需要`DbUsers`对象的地方使用它.无论如何,表不应包含百列.此外,您通常不会选择数百万用户,但很少(或只有一个). (3认同)

Cos*_*ană 10

第二个更好.您只能从数据库获取所需数据,因此网络流量更轻.

您可以使用扩展方法获得相同的结果:

var user = context.DbUsers
                  .Where(x => x.u_LoginName == id)
                  .Select(x => new {...})
                  .FirstOrDefault();
Run Code Online (Sandbox Code Playgroud)