使用 LINQ 选择和转换数据
解决的问题
在 LINQ 与 C# 3.0 一起推出之前,我们编写了大量这样的代码:
public MyEmployeeList Method()
{
MyEmployeeList aaEmployees = new MyEmployeeList();
foreach(var record in records)
{
if (record.Fields["GroupType"].Substring(0, 2) == "AA")
{
var newEmployee = new Employee();
newEmployee.Id = int.Parse(record.Fields["employee_id"].ToString());
newEmployee.FirstName = record.Fields["first_name"];
newEmployee.LastName = record.Fields["last_name"];
aaEmployees.AddEmployee(newEmployee);
}
}
return aaEmployees;
}
以下是这里发生的事情:
- 我们正在创建一个名为 aaEmployees 的空员工列表。
- 我们正在循环遍历记录集合,这些记录可能是从数据库或其他数据源返回的。
- 我们正在确定记录的组类型字段是否以“AA”开头 - 否则,我们要跳过该记录。
- 如果它确实与“AA”匹配,我们将创建一个新的员工记录并设置其属性以匹配记录中的值。
- 然后我们将新的员工对象添加到我们的员工列表中。
- 一旦我们循环,我们就会返回员工对象的集合,并筛选出仅包含以“AA”开头的 GroupType 的员工。
将该代码与以下代码进行比较:
return from record in records
where record.Fields["GroupType"].Substring(0, 2) == "AA"
select new Employee
{
Id = int.Parse(record.Fields["employee_id"].ToString()),
FirstName = record.Fields["first_name"],
LastName = record.Fields["last_name"]
};
挑剔的读者会发现两者的返回类型不同 - 第一个返回 MyEmployeeList,第二个返回 IEnumerable - 但显然使用第二个更流畅的语法会更好。我有一个语法检查器,它足够聪明,可以区分代码和英语 - 除了 LINQ,它会尝试修复我的语法,误以为它是纯英语。我们所有的代码都应该如此易于理解。
LINQ 是一种集合操作查询语言 - 它通过使集合操作通用化来自动化软件中常见的大量繁重工作和代码。
我们的场景
我们的任务是编写一个业务层,用于过滤和组织查询返回的一组结果。结果中包含某些需要转换、过滤、排序和分组的元素。重要的是要了解,使用 LINQ,结果可能来自数据库,可能来自文件系统,或者通过监听网络套接字,或者可能是硬编码的。结果如何传递给我们在很大程度上并不重要 - LINQ 的设计完全是通用的,它执行我们将要使用的集合操作。
首先,我们有一组 Employee 对象,就像我们在第一部分中查看的查询结果一样,但未过滤以 AA 开头的组类型。因此,我们的 Employee 对象如下所示:
public class Employee
{
public string FirstName { get; set; }
public string LastName { get; set; }
public int Id { get; set; }
public string GroupCode { get; set; }
public List<string> Addresses { get; set; }
}
非常简单。为了本指南的目的,我们将使用以下代码创建一组三个员工:
List<Employee> employees = new List<Employee>
{
new Employee { Id = 1, FirstName = "Chris", LastName = "Behrens", GroupCode = "AA123", Addresses = new List<string>{"7814 Vandalia Avenue Apt 3b Los Angeles CA 91610"} },
new Employee { Id = 2, FirstName = "Sam", LastName = "Smith", GroupCode = "AA128", Addresses = new List<string>{ "7814 Vandalia Avenue Apt 3b Los Angeles CA 91610" } },
new Employee { Id = 3, FirstName = "Gill", LastName = "Bates", GroupCode = "ZZ867", Addresses = new List<string>{"2810 Pisces Ct Albuequerque, NM 87144"} }
};
此集合包含在名为Employees的 List 变量中。我们需要一个员工 ID 数组 - 我们有一组要从结果中过滤的员工 ID。此语句将整个集合作为数组返回:
var employeeArray = (from e in employees
select e).ToArray();
我们的 LINQ 语句总是以 from 开头 - 这定义了我们要处理的集合以及我们将用于集合操作的变量。在这里,我们选择整个员工集,将集合变量定义为,然后选择它,即返回查询的值。最后,我们包装整个查询并使用 ToArray() 将其转换为数组。
这很棒,但现在我们有一个 Employee 对象数组 - 我们想要一个更简单的 int 数组,仅包含 ID。为了缩小选择范围,我们在设置变量上选择 ID 属性:
var employeeIdArray = (from e in employees
select e.Id).ToArray();
就这么简单。
LINQ 语法 - Fluent 与查询
出于本指南的目的,我们将重点关注 _fluent _syntax - 接近 T-SQL 和英语的语法:
var employeeIdArray = (from e in employees
select e.Id).ToArray();
除了流畅的语法之外,您还可以将 LINQ 作为函数调用来调用,这些函数调用可作为扩展方法设置类型:
var employeeIdArray = employees.Select(e => e.Id).ToArray();
在本例中,我们将 Select 调用的设置变量表示为 lambda 表达式:
.Select(e => e.Id)
就像使用流畅语法一样,您在键入时会获得针对 set 变量成员的 Intellisense。您也可以混合使用这两种语法:
var employeesAddresses = from e in employees select e.Addresses.First();
.First() 方法的作用正如您所想的那样 - 它获取列表中的第一个元素。这将返回字符串类型的 IEnumerable - 地址类型,并且它将包含员工集中每个员工列出的第一个地址。
免责声明:本内容来源于第三方作者授权、网友推荐或互联网整理,旨在为广大用户提供学习与参考之用。所有文本和图片版权归原创网站或作者本人所有,其观点并不代表本站立场。如有任何版权侵犯或转载不当之情况,请与我们取得联系,我们将尽快进行相关处理与修改。感谢您的理解与支持!
请先 登录后发表评论 ~