LINQ Operators之过滤(Filtering)
转:http://www.cnblogs.com/lifepoem/archive/2011/11/16/2250676.html
在本系列博客前面的篇章中,已经对LINQ的作用、C# 3.0为LINQ提供的新特性,还有几种典型的LINQ技术:LINQ to Objects、LINQ to SQL、Entity Framework进行了比较详细的介绍,至此,我们应该了解了各种LINQ技术之间的联系和区别。千里之行始于足下,这些基础理论是理解和使用LINQ 的关键。但是我们在前面的文章中对于LINQ查询运算符(LINQ Operators)并没有完整的介绍,这就是接下来这几篇博客中所要做的工作。大家可以按顺序依次对各个LINQ Operators进行学习,也可以把他们看成一个reference,作为参考查询之用。
示例数据
在这几篇讨论LINQ Operators的文章中,所有的示例都会(如果需要)用到下面的names数组:
string[] names = { "Tom", "Dick", "Harry", "Mary", "Jay" };
所有查询数据库的示例都会假设我们创建了强类型的DataCotnext变量dataContext,如下:

var dataContext = new LifePoemContext ("connection string...");
...
public class LifePoemContext : DataContext
{
public LifePoemContext (string cxString) : base (cxString) {}
public Table<Customer> Customers { get { return GetTable<Customer>(); } }
public Table<Purchase> Purchases { get { return GetTable<Purchase>(); } }
} [Table] public class Customer
{
[Column(IsPrimaryKey=true)] public int ID;
[Column] public string Name; [Association (OtherKey="CustomerID")]
public EntitySet<Purchase> Purchases = new EntitySet<Purchase>();
} [Table] public class Purchase
{
[Column(IsPrimaryKey=true)] public int ID;
[Column] public int? CustomerID;
[Column] public string Description;
[Column] public decimal Price; EntityRef<Customer> custRef;
[Association (Storage="custRef",ThisKey="CustomerID",IsForeignKey=true)]
public Customer Customer
{
get { return custRef.Entity; } set { custRef.Entity = value; }
}
}

上面的DataContext和实体类是LINQ to SQL工具(如通过Visual Studio新增一个”LINQ to SQL Classes” Item)生成的简化版本。其中Customer和Purchase包含了一个简单的1:多关系,下面是对应的SQL表定义:

create table Customer
(
ID int not null primary key,
Name varchar(30) not null
)
create table Purchase
(
ID int not null primary key,
CustomerID int references Customer (ID),
Description varchar(30) not null,
Price decimal not null
)

Filtering Operators
IEnumerable<TSource> → IEnumerable<TSource>
返回输入sequence中元素的一个子集
Operator |
说明 |
SQL语义 |
Where |
返回符合给定条件的elements子集 |
WHERE |
Take |
返回开始的N个元素,忽略剩下的元素 |
WHERE ROW_NUMBER()... 或TOP n 子句 |
Skip |
忽略开始的N歌元素,返回之后的元素 |
WHERE ROW_NUMBER()... 或NOT IN (SELECT TOP n...) |
TakeWhile |
返回输入sequence中的元素,直到指定条件为false,然后忽略剩下的元素 |
Exception thrown |
SkipWhile |
忽略输入sequence中的元素,直到指定条件为false,然后返回剩下的元素 |
Exception thrown |
Distinct |
返回去除重复元素的sequence |
SELECT DISTINCT... |
对每一个过滤方法而言,总是得到一个少于或等于初始元素个数的序列,而不可能返回更多的元素!并且这些元素不会经过任何改变,而是与原始元素一致。
Where
参数 |
类型 |
Source sequence |
IEnumerable<TSource> |
Predicate/条件 |
TSource => bool or (TSource,int) => boola |
a带索引的lambda表达式在LINQ to SQL和Entity Framework中不可用。
查询表达式语法:where bool-expression
Enumerable.Where实现
Enumerable.Where的内部实现大致如下(略去null引用的检查):

public static IEnumerable<TSource> Where<TSource>
(this IEnumerable<TSource> source, Func<TSource, bool> predicate)
{
foreach (TSource element in source)
if (predicate(element))
yield return element;
}

介绍
Where返回输入sequence中满足指定条件的elements,比如:
string[] names = { "Tom", "Dick", "Harry", "Mary", "Jay" };
IEnumerable<string> query = names.Where(name => name.EndsWith("y"));
// Result: { "Harry", "Mary", "Jay" }
对应的查询表达式语法:
IEnumerable<string> query = from n in names
where n.EndsWith("y")
select n;
在一个查询中where子句可以出现多次并且可以和let子句搭配使用:

string[] names = { "Tom", "Dick", "Harry", "Mary", "Jay" };
IEnumerable<string> query = from n in names
where n.Length > 3
let u = n.ToUpper()
where u.EndsWith("Y")
select u;
// Result: { "HARRY", "MARY" }

索引过滤
Where的条件支持第二个可选参数,类型为int,它的值等于每个element在输入sequence中的位置,这样我们就可以在lambda表达式中使用这个index信息。比如,下面的例子忽略index为单数的elements:
IEnumerable<string> query = names.Where((n, i) => i % 2 == 0);
// Result: { "Tom", "Harry", "Jay" }
如果你在LINQ to SQL或Entity Framework中使用索引参数,将会抛出异常。
LINQ to SQL和EF中的SQL LIKE 比较
下面这些字符串方法会被翻译成SQL的LIKE操作符:Contains、StartsWith、EndsWith。
比如:c.Name.Contains ("abc") 翻译成customer.Name LIKE '%abc%' (或者与之等价的参数版本)。
需要注意的是,在使用Contains时,我们只能用来与本地计算的表达式进行比较,如果要和另外一列进行比较,我们必须借助于SqlMethod.Like方法:
IQueryable<Purchase> query = purchases
.Where(p => SqlMethods.Like(p.Description, "%" + p.Customer.Name + "%"))
.OrderBy(p => p.ID)
.Select(p => p);
LINQ to SQL和EF中的WHERE x IN (..., ..., ...)
对于LINQ to SQL和EF,我们可以在过滤条件中对一个本地集合应用Contains方法,比如:
string[] chosenOnes = { "Tom", "Jay" }; IQueryable<Customer> query =
from c in dataContext.Customers
where chosenOnes.Contains(c.Name)
select c;
这会映射到SQL的IN操作符,即:WHERE customer.Name IN ("Tom", "Jay")。如果本地集合是一个entities数组或其他的非标量类型,LINQ to SQL和EF可能会生成EXISTS子句。
Take和Skips
参数 |
类型 |
Source sequence |
IEnumerable<TSource> |
获取或忽略的elements个数 |
int |
Take返回前面n个元素并丢弃剩下的元素;Skip丢弃前面n个元素并返回剩下的元素。这两个方法通常一起使用以实现web页面的数据分页效果,让用户能在一个大型的结果集上进行导航,比如:

// 假设用户在一个图书数据库中查找包含"mercury"的所有图书
// 如果查找结果包含100条记录,下面的查询会返回前面20条
IQueryable<Book> query = dataContext.Books
.Where (b => b.Title.Contains ("mercury"))
.OrderBy (b => b.Title)
.Take (20); // 下面的查询则返回第21到40行数据(第2页)
IQueryable<Book> query = dataContext.Books
.Where (b => b.Title.Contains ("mercury"))
.OrderBy (b => b.Title)
.Skip (20).Take (20);

对于SQL Server 2005,LINQ to SQL和EF 会把Take和Skip翻译成ROW_NUMBER函数,而对于更早的SQL Server版本,它们会被翻译成Top n子句。
TakeWhile和SkipWhile
参数 |
类型 |
Source sequence |
IEnumerable<TSource> |
Predicate |
TSource => bool or (TSource,int) => bool |
TakeWhile遍历输入sequence,返回每个element,直到给定的测试条件为false,然后忽略剩下的elements:
int[] numbers = { 3, 5, 2, 234, 4, 1 };
var takeWhileSmall = numbers.TakeWhile(n => n < 100); // { 3, 5, 2 }
SkipWhile遍历输入sequence,忽略每个element,直到给定的测试条件为false,然后返回剩下的elements:
int[] numbers = { 3, 5, 2, 234, 4, 1 };
var skipWhileSmall = numbers.SkipWhile(n => n < 100); // { 234, 4, 1 }
TakeWhile和SkipWhile没有对应的SQL翻译,如果在LINQ-to-db查询中使用他们会导致运行时错误。
Distinct
Distinct返回去除了重复元素之后的输入sequence,在确定元素是否重复时只能使用默认的相等比较方法:
// The following returns distinct letters in a string
char[] distinctLetters = "HelloWorld".Distinct().ToArray();
string s = new string (distinctLetters); // HeloWrd
我们可以在string变量上直接调用LINQ方法,因为string实现了IEnumerable<char>。
在下一篇博客中,会详细讨论LINQ运算符中的数据转换:Select和SelectMany。
LINQ Operators之过滤(Filtering)的更多相关文章
- LINQ之路11:LINQ Operators之过滤(Filtering)
在本系列博客前面的篇章中,已经对LINQ的作用.C# 3.0为LINQ提供的新特性,还有几种典型的LINQ技术:LINQ to Objects.LINQ to SQL.Entity Framework ...
- LINQ之路16:LINQ Operators之集合运算符、Zip操作符、转换方法、生成器方法
本篇将是关于LINQ Operators的最后一篇,包括:集合运算符(Set Operators).Zip操作符.转换方法(Conversion Methods).生成器方法(Generation M ...
- LINQ之路14:LINQ Operators之排序和分组(Ordering and Grouping)
本篇继续LINQ Operators的介绍,这里要讨论的是LINQ中的排序和分组功能.LINQ的排序操作符有:OrderBy, OrderByDescending, ThenBy, 和ThenByDe ...
- LINQ之路12:LINQ Operators之数据转换(Projecting)
本篇继续LINQ Operators的学习,这里我们讨论的是数据转换的两种方式:Select和SelectMany,看似简单常用的两种运算符,却也大有讲究.我们会在本篇详细介绍他们的使用方式和适用的场 ...
- LINQ之路15:LINQ Operators之元素运算符、集合方法、量词方法
本篇继续LINQ Operators的介绍,包括元素运算符/Element Operators.集合方法/Aggregation.量词/Quantifiers Methods.元素运算符从一个sequ ...
- 感受一下.net中用 lambda与 linq 做数据集过滤的不同
lambda: ids.Add( _hahahacontext .hahahamodel .FirstOrDefault( a => //lambda做过滤 a.name == "张宏 ...
- LINQ之路13:LINQ Operators之连接(Joining)
Joining IEnumerable<TOuter>, IEnumerable<TInner>→IEnumerable<TResult> Operator 说明 ...
- variant的过滤 | filtering and prioritizing genetic variants
WGS和WES测序和分析会产生大量的variant数据. 显然直接分析全部的variant是非常不靠谱的. 做疾病的话,有一些常用的过滤套路. variant作用于基因表达主要分两大类: 1. cod ...
- LINQ LINQ Operators and Lambda Expression - Syntax & Examples
LINQ is a cool feature in C# 3.0. Most of the developers are struggling for the syntax and examples. ...
随机推荐
- .Net程序员玩转Android系列之三~快速上手(转)
转自http://www.cnblogs.com/HouZhiHouJueBlogs/p/3962122.html 快速环境搭建和Hello World 第一步:JAVA SDK(JDK)的安装: 官 ...
- Objective-C:模拟按钮点击事件理解代理模式
OC中的协议(Protocol)和和.NET中的接口(Interface)类似,简单来讲,就是一系列方法的列表,其中声明的方法可以被任何类实现.不同的是,在.NET中,如果某个类实现了一个接口,就必须 ...
- chkconfig命令
chkconfig --list #列出系统所有的服务启动情况chkconfig --add xxx #增加xxx服务chkconfig --de ...
- ACTIVITI 表结构数据分析
ACTIVITI ACT_RU_EXECUTION 表 这个表是工作流程的核心表,流程的驱动都和合格表有密切的关系. 一般来讲一个流程实例都有一条主线.如果流程为直线流程,那么流程实例在这个表 ...
- windows下mysql主从同步备份步骤
目的:有两台MySQL数据库服务器A和B,使A为主服务器,B为从服务器,初始状态时,A和B中的数据信息相同,当A中的数据发生变化时,B也跟着发生相应的变化,使得A和B的数据信息同步,达到备份的目的. ...
- 告别硬编码-发个获取未导出函数地址的Dll及源码
还在为找内核未导出函数地址而苦恼嘛? 还在为硬编码通用性差而不爽吗? 还在为暴搜内核老蓝屏而痛苦吗? 请看这里: 最近老要用到内核未导出的函数及一些结构,不想再找特征码了,准备到网上找点符号文件解析的 ...
- linux安装svn服务端不使用apache
一.安装 1.查看是否安装cvs rpm -qa | grep subversion 2.安装 yum install subversion 3.测试是否安装成功 /usr/bin/svnserve ...
- 【C语言学习】-03 循环结构
本文目录 循环结构的特点 while循环 do...while循环 for循环 回到顶部 一.循环结构的特点 程序的三种结构: 顺序结构:顺序执行语句 分支结构:通过进行一个判断在两个可选的语句序列之 ...
- HDU 1203-Program D
Description Speakless很早就想出国,现在他已经考完了所有需要的考试,准备了所有要准备的材料,于是,便需要去申请学校了.要申请国外的任何大学,你都要交纳一定的申请费用,这可是很惊人的 ...
- 到目前为止,Linux下最完整的Samba服务器配置攻略 (转)
http://blog.chinaunix.net/uid-23069658-id-3142052.html 安装平台为UBUNTU 14.04,直接软件中心安装samba, service smb ...