Linq (Language Integrated Query,语言集成查询),是微软公司提供的一项新技术,它能够将查询功能引入到.NET 3.5 所支持的编程语言中,例如C#,Visual Basic.NET。查询操作通过编程语言自身来表达,而不再是以字符串的形式嵌入到应用程序中。
Linq主要包含下面四个组件:
Linq to Objets、Linq to Sql、Linq to DataSet和Linq to XML,它们分别用于查询和处理对象数据(如集合等)、关系数据、DataSet对象数据和XML结构的数据(如XML文件)。
1.什么是Linq?
“查询”是一组指令,使用这些指令可以从一个或是对个给定的数据源中检索数据,并返回指定表现形式的结果。Linq也是一种查询,它集成于.NET3.5之中,可以为C#等编程语言提供强大的方便的查询功能,并与其整合一体,成为Visual Studio 2008中的一组全新的功能。
Linq 也是一种查询技术。下面我们使用Linq从以整数集合中查询数值小于10的元素。其中,
From:子句描述被查询的数据源;
Where:子句指定元素所满足的过滤条件;
Select:子句制定查询结果的表现形式。
List
<
int
>
myDataSource
=
new
List
<
int
>
{
1
,
2
,
23
,
4
,
15
,
26
,
15
,
5
,
45
,
61
,
8
,
9
};
var result
=
from i
in
myDataSource
where
i
<
10
select i;
反思:传统编程中,查询数据往往需要将字符串嵌入到应用程序中进行查询操作,这样一般不会检查被查询的数据类型。Linq使得查询操作成为编程语言的一部分,可以象书写代码一样,方便的创建查询和表达式。
2. Linq基本组成组件
Linq是一项突破性创新技术,将数据、对象和日常编程语言之间架起一座桥梁。几乎可以查询和操作任何存储形式的数据。
(1) Linq to Sql组件:可以查询关系型数据库的数据,并可以提供其他操作,如检索、插入、修改、删除、排序、聚合、分区等。
(2) Linq to DataSet组件:查询DataSet对象中的数据。
(3) Linq to Object组件:可以查询IEnumerable或是IEnumerable<T> 集合对象,即能够查询任何可以枚举的集合,如数组(Array和ArrayList)、泛型字典Dictinary<T>等,以及用户自定义的集合,而不需要使用Linq提供程序或API。
(4) Linq to XML组件:查询和操作XML结构的数据。
3. 开发环境
关于开发环境,简单补充如下:
要开发ASP.NET 3.0/3.5Web 应用程序,则需要安装Microsoft Visual Studio 2008集成开发环境(IDE)。因为Linq被.NET 3.5所支持,故若是创建Linq的Web应用程序或是Windows Form应用程,必须使用.NET 3.5.
4. 第一个使用Linq的web应用程序
(1)创建一个WebSite,命名 Linq_Sample_1;
(2)创建一个整形数组intDataSource,长度100,for初始化该数组(0~99);
(3)创建Linq查询表达式,从数组中查询小于20的元素。并保存的query变量中。
protected
void
Page_Load(
object
sender, EventArgs e)
{
if
(
!
this
.IsPostBack)
{
LinqQueryData();
}
}
public
void
LinqQueryData()
{
int
[] intDataSource
=
new
int
[
100
];
for
(
int
i
=
0
; i
<
100
; i
++
)
{
intDataSource[i]
=
i;
}
//
创建Linq查询语句
var query
=
from i
in
intDataSource
where
i
<
20
select i;
foreach
(var q
in
query)
{
Response.Write(q.ToString()
+
"
<br/>
"
);
}
}
5. 四个重要接口
进一步学习Linq需要熟悉Linq最基本的四个接口。即:IEnumerable、IEnumerable<T>、IQueryable和IQueryable<T>,所有支持linq查询的对象,都必须直接或是间接是想IEnumerable接口。
关于四个类的详细设计,你可以参阅MSDN。
6. 与Linq相关的命名空间
.NET 3.5 提供了多个与Linq相关的命名空间,如:
(1) System.Linq 命名空间,提供支持使用Linq进行查询的类和接口,如Enumerable类、Queryable类、IQueryable 接口、IQueryable<T>接口、IorderedQueryable接口、IorderQueryable<T>接口等。
(2) System.Data.Linq 命名空间,提供与Linq to Sql相关的类、结构、接口和枚举,如Table<T>类,EntityRef<T>结构、EntitySet<T>结构、IExecuteResult接口、IFunctionResult接口、IMultipleResults接口、ISingleResult<T>接口等。
(3) System.Xml.Linq命名空间,提供与Linq to XML相关的类和枚举,如XDocument类、XElement类、XAttribute类、XDeclaration类、XName类、XNamespace类、XText类等。
7. Linq 查询的优势
这里提前强调是,为便于讲解或是体验,定义数据库MyLinqDB为本学习笔记贯穿始终的数据库名称。
1)、查询集合中的数据
传统方法为使用for或是foreach语句,而Linq使用查询表达式查询集合中的数据。书写简洁、容易添加判断条件。
7.1.1 Foreach 查询集合
private
void
OldArrayQuery()
{
string
[] datasource
=
new
string
[
10
];
for
(
int
i
=
0
; i
<
10
; i
++
)
{
datasource[i]
=
"
LINQ
"
+
i.ToString().PadLeft(
5
,
'
0
'
);
}
//
创建一动态数组,保存查询结果
ArrayList result
=
new
ArrayList();
foreach
(
string
s
in
datasource)
{
int
index
=
Int32.Parse(s.Substring(
4
));
if
(index
%
2
==
0
)
{
result.Add(s);
}
}
foreach
(
string
s
in
result)
{
Response.Write(s
+
"
<br/>
"
);
}
}
7.1.2 Linq查询数组
private
void
LinqArrayQuery()
{
string
[] datasource
=
new
string
[
10
];
for
(
int
i
=
0
; i
<
10
; i
++
)
{
datasource[i]
=
"
LINQ
"
+
i.ToString().PadLeft(
5
,
'
0
'
);
}
var result
=
from s
in
datasource
let index
=
int
.Parse(s.Substring(
4
))
where
index
%
2
==
0
select s;
foreach
(
string
s
in
result)
{
Response.Write(s
+
"
<br/>
"
);
}
}
反思:
Foreach语句往往与查询条件相互分隔,代码相对繁琐;Linq,一个查询表达式即可实现查询和配置查询两个功能。代码相对较少,集成度也较高。
7.2.1查询数据库中的数据
传统的方法为使用SQL语句或是存储过程直接进行查询;而是用Linq查询数据库中的数据,需要为该数据库创建实体类,然后使用Linq查询表达式查询相关数据。
传统的方法无非创建数据库连接对象(Connection),查询语句”Select * from Mytable”,或有参数或无参数,接着再创建一个SQL语句的命令对象Command,调用ExecuteReader()方法读取数据,并保存在变量中供使用。
具体实现代码这里不做赘述。
Linq查询数据库中的数据的过程:
(1) 为MyLinqDB数据库创建DBML文件LinqDB.dbml,并为表创建实体类 。
(2) 创建LinqDB数据库的数据上下文类的实例,连接字符串保存在strConn。
(3) 创建查询表达式,将查询结果存在results变量中。
(4) 使用foreach语句显示results变量中的查询结果。
代码比较如下:
(1) 传统方法:
private
void
OldSQLQuery()
{
//
创建数据库连接
SqlConnection con
=
new
SqlConnection(strCon);
//
创建SQL语句、
string
cmdText
=
"
select * from Products
"
;
//
创建SqlCommand 对象 执行SQL 命令
SqlCommand cmd
=
new
SqlCommand(cmdText, con);
con.Open();
//
执行查询操作
SqlDataReader reader
=
cmd.ExecuteReader();
while
(reader.Read())
{
if
(reader[
"
ProductName
"
].ToString().Length
>
6
)
{
Response.Write(reader[
"
ProductName
"
].ToString()
+
"
</br>
"
);
}
}
reader.Close();
con.Close();
}
(2) Linq to SQL :
private
void
LinqSQLQuery()
{
LinqDBMLDataContext db
=
new
LinqDBMLDataContext(strCon);
var results
=
from p
in
db.Products
where
p.ProductName.Length
>
10
select p;
foreach
(var i
in
results)
{
Response.Write(i.ProductName
+
"
</br>
"
);
}
}
代码简洁明朗。
3)、查询DataSet对象中的数据
传统方法往往需要使用foreach语句等,遍历读取。Linq则使用查询表达式查询对象中的数据。
代码比较如下:
(1) 传统方法:
private
DataSet GetDataSet()
{
SqlConnection con
=
new
SqlConnection(strCon);
string
cmdText
=
"
select * from products
"
;
SqlDataAdapter da
=
new
SqlDataAdapter(cmdText, con);
con.Open();
DataSet ds
=
new
DataSet();
da.Fill(ds,
"
Product
"
);
con.Close();
return
ds;
}
private
void
OldDataSetQuery()
{
DataSet ds
=
GetDataSet();
foreach
(DataRow row
in
ds.Tables[
0
].Rows)
{
if
(row[
"
ProductName
"
].ToString().Length
>
10
)
{
Response.Write(row[
"
ProductName
"
].ToString()
+
"
<br/>
"
);
}
}
}
(2) Linq to DataSet
private
void
LinqDataSetQuery()
{
DataSet ds
=
GetDataSet();
var results
=
from p
in
ds.Tables[
0
].AsEnumerable()
where
p.Field
<
string
>
(
"
ProductName
"
).Length
>
10
select p;
foreach
(var v
in
results)
{
Response.Write(v.Field
<
string
>
(
"
ProductName
"
).ToString()
+
"
<br/>
"
);
}
}
4)、查询XML文件
传统的方法往往使用XPath。Linq使用查询表达式查询XML文件中的数据。
代码比较如下:
(1) 传统方法
private
string
xmlString
=
"
<Books>
"
+
"
<Book ID=\
"
101
\
"
>
"
+
"
<No>0001</No>
"
+
"
<Name>Book 0001</Name>
"
+
"
<Price>120</Price>
"
+
"
<Remark>This is a book 0001.</Remark>
"
+
"
</Book>
"
+
"
<Book ID=\
"
102
\
"
>
"
+
"
<No>0002</No>
"
+
"
<Name>Book 0002</Name>
"
+
"
<Price>120</Price>
"
+
"
<Remark>This is a book 0002.</Remark>
"
+
"
</Book>
"
+
"
<Book ID=\
"
103
\
"
>
"
+
"
<No>0003</No>
"
+
"
<Name>Book 0003</Name>
"
+
"
<Price>120</Price>
"
+
"
<Remark>This is a book 0003.</Remark>
"
+
"
</Book>
"
+
"
</Books>
"
;
private
void
OldXMLQuery()
{
XmlDocument doc
=
new
XmlDocument();
doc.LoadXml(xmlString);
string
path
=
"
/Books/Book
"
;
XmlNodeList nodeList
=
doc.SelectNodes(path);
foreach
(XmlNode node
in
nodeList)
{
foreach
(XmlNode n
in
node.ChildNodes)
{
if
(n.InnerXml
==
"
Book 0002
"
)
{
Response.Write(node.LocalName
+
node.Attributes[
"
ID
"
].Value
+
"
<br/>
"
);
}
}
}
}
(2) Linq to XML
private
void
LinqXMLQuery()
{
XElement xe
=
XElement.Parse(xmlString);
var results
=
from x
in
xe.Elements()
where
(
string
)x.Element(
"
Name
"
)
==
"
Book 0002
"
select x;
foreach
(var e
in
results)
{
Response.Write(e.Name.LocalName
+
e.Attribute(
"
ID
"
).Value
+
"
<br/>
"
);
}
}