在进行LINQ查询时,经常需要从序列中获取一个或多个元素。在这种情况下,FirstOrDefault和SingleOrDefault方法非常有用。这两个方法都可以用来从序列中获取元素,但它们在处理序列元素数量时的行为有所不同。本文将通过一个控制台应用程序来解释这两个方法的不同之处。
实体类是在LINQ到SQL类文件(.dbml文件)中创建并存储的。当打开一个.dbml文件时,O/R设计器就会打开。它是一个DataContext类,包含连接数据库和操作数据库数据的方法和属性。DataContext的名称对应于为.dbml文件提供的名称。
在解决方案资源管理器中右键单击项目,然后转到“添加”并单击“类…”。
从列表中选择“LINQ到SQL类”,为dbml名称命名为“User”,然后单击“添加”。
从数据库的服务器资源管理器中拖动User表并将其放到“User.dbml”文件的O/R设计器表面上。
将查看FirstOrDefault和SingleOrDefault方法的不同场景。
如果序列返回0个元素,那么FirstOrDefault方法将为类型设置默认值。假设从数据库表中检索一个特定的记录,而该特定记录在数据库表中不存在,那么序列包含0个元素,FirstOrDefault方法将为该对象设置一个null值。
在以下代码片段中,序列不包含元素,然后FirstOrDefault方法为对象类型设置一个null值,然后执行catch块。在catch块中定义NullReferenceException作为参数,表示当为对象设置null值并从该对象检索数据时,执行此catch块。
C# using System; using System.Linq; namespace FirstOrSingle { class Program { static void Main(string[] args) { using (UserDataContext dataContext = new UserDataContext()) { var users = from user in dataContext.Users where user.Id == 5 select user; var firstUser = users.FirstOrDefault(); try { Console.WriteLine("Name : {0} Age : {1}", firstUser.Name, firstUser.Age); } catch (NullReferenceException ex) { Console.WriteLine("No Record Found"); Console.Write(ex.Message); } Console.ReadKey(); } } } }
运行应用程序后,得到的结果表示由于从具有null值的对象中检索值,因此执行了catch块。
如果序列只包含1个元素,那么FirstOrDefault和SingleOrDefault方法之间没有区别,两者都会返回同一个元素。例如:
C# using System; using System.Linq; namespace FirstOrSingle { class Program { static void Main(string[] args) { using (UserDataContext dataContext = new UserDataContext()) { var users = from user in dataContext.Users where user.Id == 4 select user; var firstUser = users.FirstOrDefault(); var singleUser = users.SingleOrDefault(); try { Console.WriteLine("Result By FirstOrDefault Method"); Console.WriteLine("Name : {0} Age : {1}", firstUser.Name, firstUser.Age); Console.WriteLine("======================================================"); Console.WriteLine("Result By SingleOrDefault Method"); Console.WriteLine("Name : {0} Age : {1}", singleUser.Name, singleUser.Age); } catch (NullReferenceException ex) { Console.Write(ex.Message); } Console.ReadKey(); } } } }
运行应用程序后,得到的结果表示两种方法的结果相同。
如果序列包含多个元素,那么FirstOrDefault方法只返回序列中的第一个元素。以下代码片段显示了使用FirstOrDefault方法从这个序列中获取第一个元素。
C# using System; using System.Linq; namespace FirstOrSingle { class Program { static void Main(string[] args) { using (UserDataContext dataContext = new UserDataContext()) { var users = from user in dataContext.Users select user; try { var firstUser = users.FirstOrDefault(); Console.WriteLine("Name : {0} Age : {1}", firstUser.Name, firstUser.Age); } catch (InvalidOperationException ex) { Console.Write(ex.Message); } Console.ReadKey(); } } } }
运行应用程序后,从序列中获取了第一个元素。
当序列包含多个元素并使用SingleOrDefault方法获取元素时,会得到一个异常,表示序列包含多个元素。以下代码片段显示了这一点:
C# using System; using System.Linq; namespace FirstOrSingle { class Program { static void Main(string[] args) { using (UserDataContext dataContext = new UserDataContext()) { var users = from user in dataContext.Users select user; try { var singleUser = users.SingleOrDefault(); Console.WriteLine("Name : {0} Age : {1}", singleUser.Name, singleUser.Age); } catch (InvalidOperationException ex) { Console.Write(ex.Message); } Console.ReadKey(); } } } }