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

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

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

你可以看到我想要做的就是获取名称和电子邮件,但是在我看来,这个LINQ查询正在将所有的东西都存储在该用户的数据库中,然后将它带回来,然后让我得到我想要的。

我一直在做一些研究,并find了以下的select:

 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 } 

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

如果你只想得到两个字段,那么你应该查询执行之前投影你的实体(在这种情况下,当你调用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 } 

只是为了显示完整的图片,没有投影,你会得到第一个find的用户的所有领域:

 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 

第二个更好。 您只能从数据库获得所需的数据,因此networkingstream量较轻。

你可以用扩展方法得到相同的结果:

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

如果您不需要整个实体,但是需要一些值,则使用new {name = s.u_Name, email = s.u_Email} 。 因为这个东西对于build筑来说是很“轻”的。 当你得到FirstOrDefault的实体时,它保存在DBContext中,但是你不用做任何事情。 所以,我build议你只获取你需要的数据。