LINQ技术实际包括LINQ(对象操作)、DLINQ((数据操作)、XLINQ(Xml操作)三种技术
1.LINQ要解决的问题
长期以来,开发社区形成以下格局:
面向对象与数据访问两个领域长期分裂,各自为政
编程语言中的数据类型与数据库中的数据类型形成两套体系。例如:
C# 中字符串用 string 表示
SQL 中字符串用 NVarchar/Varchar/Char 表示
SQL 编码体验落后
没有智能感应
没有严格意义上的强类型和类型检查
SQL 和 XML 都有各自的查询语言,而对象没有自己的查询语言
2.LINQ(Language Integrated Query)即语言集成查询
LINQ 是一组语言特性和API,使得你可以使用统一的方式编写各种查询。查询的对象包括XML、对象集合、SQL Server 数据库等等。
LINQ 主要包含以下三部分:
1.LINQ to Objects 主要负责对象的查询(是指直接对任意IEnumerable集合使用LINQ查询,无需使用中间LINQ程序或API。其他都是需要使用中间LINQ程序或API,详细案例可以看 第30章 资料
LINQ To Object 提供的是内存中集合数据的实体映射.
其用法见我的博客 http://blog.youkuaiyun.com/goodshot/article/details/8922719)
2.LINQ to XML 主要负责 XML 的查询(其用法见我的博客 http://blog.youkuaiyun.com/GoodShot/article/details/8919595)
3.LINQ to ADO.NET 主要负责数据库的查询
1)LINQ to SQL(轻量级的ORM模型,诟病很多,微软尽管没放弃,但大家都言会淘汰)
2)LINQ to DataSet(其用法见我的博客 http://blog.youkuaiyun.com/goodshot/article/details/8922596)
3)LINQ to Entities(重量级的ORM模型?)
3.*** to A ,基本是都是指最终LINQ都支持对他们的查询,在查询语句方式中即是指在关键词"in"后面的数据源是A的相应对象
4.事实上,LINQ查询存在以下两种形式
1)Method Syntax, 查询方法方式
主要利用 System.Linq.Enumerable 类中定义的扩展方法和Lambda表达式方式进行查询
上一章的例子都是以这种方式查询
2)Query Syntax, 查询语句方式
一种更接近 SQL 语法的查询方式
可读性更好
5.查询语句与查询方法存在着紧密的关系
CLR本身并不理解查询语句,它只理解查询方法
编译器负责在编译时将查询语句翻译为查询方法
大部分查询方法都有对应的查询语句形式:如 Select() 对应select 、 OrderBy() 对应 orderby
部分查询方法目前在C#中还没有对应的查询语句:如 Count()和Max() 这时只能采用以下替代方案
查询方法
查询语句 + 查询方法的混合方式;
一般情况下,建议使用可读性更好的查询语句
例1:
int count =
(
from p in foxRiver8
where p.Age <= 30
select p
)
.
Count
();
等同
int count = foxRiver8
.Where(p => p.Age <= 30)
.
Count
();
例2:
int maxAge = (from p in foxRiver8
select p.Age).
Max
();
等同
int maxAge = foxRiver8
.Select(p => p.Age)
.
Max
();
例3:
int maxAge = (from p in foxRiver8
select p.Age).
M
in
();
等同
int maxAge = foxRiver8
.Select(p => p.Age)
.
M
in
();
例4:
doubleaverageAge = (from p in foxRiver8
select p.Age).
Average
();
等同
doubleaverageAge = foxRiver8
.Select(p => p.Age)
.
Average
();
例5:
IntsumAge = (from p in foxRiver8
select p.Age).
Sum
();
等同
intsumAge = foxRiver8
.Select(p => p.Age)
.
Sum
();
例6:
var q = foxRiver8
.OrderBy(p => p.FirstName)
.
ThenBy
(p => p.LasName)
.
ThenBy
(p => p.Age);
等同
var q = from p in foxRiver8
orderby
p.FirstName, p.LasName, p.Age
select p;
6.LINQ查询语句的理解,以下面程序为例
List<Person> foxRiver8 = GetFoxRiver8();
var q = from p in foxRiver8
where p.Age <= 30 && p.FirstName.Length == 7
orderby p.Age descending
select new{
Name = p.FirstName + " " + p.LasName,
Age = p.Age};
foreach (var item in q)
{
Console.WriteLine(item.Name + " " + item.Age);
}
最终linq语句(from ...in where...orederby...select)返回结果是这么解释的:从
foxRiver8 中(以遍历的方式)取出一个对象(Person),赋值给p(姑且认为是“赋值”,p的类型编译器自动判断),以p作为依据,使用其属性通过where筛选出所有符合条件的对象(即先运行from..in... where...),然后以这些对象为基础,按照select语句中的形式组成一组新的对象集合(每个对象均是由Name和Age两个属性(?or字段?)组成,然后再按照orderby提供的排序标准,进行排序,最后,将排序后的最终集合,赋给q(则q是以foxRiver8中的符合条件的对象为基础,构成的一个新的集合(其实现了IEnumerable接口))
7.查询分为以下三步:获取数据源、定义查询、执行查询;
定义查询后,查询直到需要枚举结果时才被真正执行,这种方式称为“延迟执行(deferred execution)”;
当查询方法返回单一值时,查询立即执行;
因此,可以通过以下技巧在定义查询时就强制执行查询;
var even = numbers
.Where(p => p % 2 == 0)
.Select(p =>
{
Console.WriteLine("Hi! " + p.ToString());
return p;
}).Count();
8.
LINQ以from开始,结束于select或group子句
9.
§Lambda表达式的格式为:
(参数列表)=>表达式或语句块
§可以有多个参数、一个参数、无参数,参数类型可以是显式或者隐式。
例如:
§ (x,y)=>x*y //多参数,隐式参数=>表达式
§ x=>x*10 //单参数,隐式参数=>表达式
§ x=>{return x*10} //单参数,隐式参数=>语句块
§ ()=>Console.WriteLine(); //无参数,语句块
解释:
§Lambda表达式的参数类型可以省略,因为可以根据使用上下文进行推断。
§Lambda表达式的主体(Body)可以是表达式,也可以是语句块。
§Lambda表达式传入的实参将参与类型推断,以及方式重载辨析。
§Lambda表达式的表达式和表达式体可以被转换成表达式树。