LINQ:
当我确定查询将返回一条记录时,使用Single()操作符比First()更有效吗?
有区别吗?
LINQ:
当我确定查询将返回一条记录时,使用Single()操作符比First()更有效吗?
有区别吗?
当前回答
如果发现匹配条件的记录超过一条,Single将抛出异常。 First将始终从列表中选择第一条记录。如果查询只返回一条记录,您可以使用First()。
如果集合为空,两者都会抛出InvalidOperationException异常。 或者你也可以使用SingleOrDefault()。如果列表为空,则不会抛出异常
其他回答
员工实体中的记录:
Employeeid = 1:只有一个具有此ID的员工
罗伯特:不止一个员工叫这个名字
Employeeid = 10:没有该ID的员工
现在有必要详细理解Single()和First()的含义。
单()
Single()用于返回表中唯一存在的单个记录,因此下面的查询将返回employeed =1的Employee,因为我们只有一个employeed为1的Employee。如果EmployeeId = 1有两条记录,那么它会抛出一个错误(请参阅下面第二个查询中的错误,其中我们使用了Firstname的示例。
Employee.Single(e => e.Employeeid == 1)
上面的操作将返回一条记录,该记录有1个employeeId
Employee.Single(e => e.Firstname == "Robert")
上面将抛出一个异常,因为表中有多个FirstName='Robert'的记录。唯一的例外是
InvalidOperationException:序列包含多个元素
Employee.Single(e => e.Employeeid == 10)
这将再次抛出异常,因为id=10的记录不存在。唯一的例外是
InvalidOperationException:序列不包含元素。
对于EmployeeId = 10,它将返回null,但是由于我们正在使用Single(),它将抛出一个错误。为了处理空错误,我们应该使用SingleOrDefault()。
第()
First()从多个记录中返回按出生日期升序排序的相应记录,因此它将返回年龄最大的'Robert'。
Employee.OrderBy(e => e. Birthdate)
.First(e => e.Firstname == "Robert")
以上应返回最老的,罗伯特按照DOB。
Employee.OrderBy(e => e. Birthdate)
.First(e => e.Employeeid == 10)
以上将抛出异常,因为id =10的记录不存在。 To avoid a null exception we should use FirstOrDefault() rather than First().
注意:当我们绝对确定First()/Single()不能返回空值时,我们只能使用它。
在这两个函数中使用SingleOrDefault()或FirstOrDefault()来处理 空异常,在没有找到记录的情况下,它将返回null。
我认识的很多人都使用FirstOrDefault(),但我更倾向于使用SingleOrDefault(),因为如果有多个,通常会出现某种数据不一致。不过,这是在处理LINQ-to-Objects。
你可以尝试简单的例子来得到不同。 异常将在第3行抛出;
List<int> records = new List<int>{1,1,3,4,5,6};
var record = records.First(x => x == 1);
record = records.Single(x => x == 1);
如果你期望一个单一的记录,在你的代码中显式总是好的。
我知道其他人已经写了为什么你要使用其中一个或另一个,但我认为我应该说明为什么你不应该使用一个,当你指的是另一个。
注意:在我的代码中,我通常会使用FirstOrDefault()和SingleOrDefault(),但这是一个不同的问题。
以一个表为例,它使用一个组合键(ID, Lang)存储不同语言的客户:
DBContext db = new DBContext();
Customer customer = db.Customers.Where( c=> c.ID == 5 ).First();
上面的代码引入了一个可能的逻辑错误(难以跟踪)。它将返回多个记录(假设您有多种语言的客户记录),但它总是只返回第一个记录……有时候可能有用……但其他人不是。它是不可预测的。
由于您的意图是返回一个单一客户使用Single();
下面的语句会抛出一个异常(这就是你在本例中想要的):
DBContext db = new DBContext();
Customer customer = db.Customers.Where( c=> c.ID == 5 ).Single();
然后,你就拍拍自己的额头,对自己说……哦!我忘了语言课了!以下是正确的版本:
DBContext db = new DBContext();
Customer customer = db.Customers.Where( c=> c.ID == 5 && c.Lang == "en" ).Single();
First()在以下场景中很有用:
DBContext db = new DBContext();
NewsItem newsitem = db.NewsItems.OrderByDescending( n => n.AddedDate ).First();
它将返回一个对象,由于您正在使用排序,它将返回最近的记录。
当您认为Single()应该显式地总是返回1条记录时,使用它将帮助您避免逻辑错误。
他们是不同的。它们都断言结果集不是空的,但single也断言结果集不超过1个。我个人在只希望有1个结果的情况下使用Single,因为返回超过1个结果是一个错误,可能应该这样对待。