Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/280.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# `从..在LINQ中的'where'或'FirstOrDefault'_C#_Linq_Entity Framework - Fatal编程技术网

C# `从..在LINQ中的'where'或'FirstOrDefault'

C# `从..在LINQ中的'where'或'FirstOrDefault',c#,linq,entity-framework,C#,Linq,Entity Framework,传统上,当我试图从数据库中为用户获取数据时,我使用了以下方法(某种程度上): 您可以看到,我所要做的就是获取名称和电子邮件,但在我看来,这个LINQ查询正在获取存储在该用户数据库中的所有内容,将其带回,然后允许我获取所需内容 我一直在做一些研究,发现了以下替代方案: var current = from s in context.DbUsers where s.u_LoginName == id select new { name = s.u_Name,

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

您可以看到,我所要做的就是获取名称和电子邮件,但在我看来,这个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
}

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

如果您只想获取两个字段,那么您应该在执行查询之前投影实体(在这种情况下,当您调用
FirstOrDefault
时,查询就会执行)。使用
选择
运算符投影到具有必填字段的匿名对象:

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

第二个更好。您只需要从数据库中获取所需的数据,这样网络流量就更轻了

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

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

如果您不需要整个实体,而是需要其中的一些值,则使用
new{name=s.u_name,email=s.u_email}
。因为,对于C结构来说,这个对象要“轻”得多。 当您使用FirstOrDefault获取实体时,它会保存在DBContext中,但您不会对其执行任何操作。
因此,我建议您只获取所需的数据。

如果您不希望收集所有数据,而只希望收集一些字段,那么第二种方法就是。当您需要较少的数据(选定数据)时,启动SQL server探查器并检查第二个查询中的差异。我看到人们在每次实际查询之前都会撒上“any”查询,以确保得到结果。。。这是一个糟糕的想法,它会创建不必要的数据库往返。。。“FirstOrDefault()”可以在一次往返到服务器的过程中很好地处理无数据情况database@NewAmbition,如果有多个结果,SingleOrDefault将引发异常。它通过查询前两个结果并在实际检索到两个结果时引发异常来确定这一点。如果检索到一个,则返回它。如果未检索到任何对象,则返回对象默认值。Hrm我必须更正以前的注释
SingleOrDefault
如果有多个结果,则抛出。我更重要的一点仍然是,FirstOrDefault、SingleOrDefault和类似Take(2)的东西在某些时候会得到您想要的东西,而其中任何一个都是到数据库的一次往返,并且比在执行查询和获得结果之前调用
.any()
要好得多。如果您不清楚何时使用这些工具,请进行大量测试,直到您了解它们的行为。不要粗鲁,但这是你们必须理解的基本行为,所以测试直到你们理解:)它突然变得如此明显。“若你们只想得到两个字段,那个么你们应该在执行查询之前投影你们的实体”若我选择两个匿名类型的属性或一个完全初始化的对象真的重要吗?后者的优点是,我可以在需要
DbUsers
对象的任何地方使用它。一个表无论如何不应该包含一百列。此外,您通常不会选择数以百万计的用户,而是选择少数(或仅选择一个)用户。还值得一提的是,您还可以将数据投影到单独的类型中。它不必是匿名类型=>
newmytype{Username=u.u_Name}
@TimSchmelter我同意通常您只选择整个对象,而不考虑需要哪些字段。但有时您应该使用遗留数据库或非规范化表(哎哟!),加载数百列成为一个真正的问题。在类似sql的语法中,您仍然可以通过与扩展方法相结合来获得单个结果:
(从…中的s选择新的{…})。FirstOrDefault()
var user = context.DbUsers
                  .Where(x => x.u_LoginName == id)
                  .Select(x => new {...})
                  .FirstOrDefault();