何谓LINQ?
LINQ即.NET 语言集成查询(.NET Language-Integrated Query (LINQ) Framework),为.NET架构中的重要组成部分。LINQ系列技术提供了针对对象(LINQ)、关系数据库(LINQ to SQL)和XML(LINQ to XML)的一致性查询体验。
什么是LINQ to XML?
LINQ to XML 使用最新的.NET Framework语言功能,相当于更新和重新设计的文档对象模型(DOM)XML编程接口。使用它,可以在.NET Framework编程语言中处理XML。
它将XML文档置于内存中,这一点很像文档对象模型(DOM)。你可以查询和修改XML文档,修改后,可以将其另存为文件,也可以将其序列化然后通过网络发送。但是,LINQ to XML与DOM不同:它提供一种新的对象模型,这好似一种更轻量的模型,使用也更方便,这种模型利用了Visual C# 2008在语言方面的改进。
LINQ to XML 最重要的优势是它与LINQ的集成。由于实现了这一集成,所以,可以对内存XML文档编写查询,以检索元素的属性和集合。LINQ to XML的查询功能与XPath和XQuery(两种老式的XML标准检索机制)具有可比性。Visual C# 2008集成LINQ后,可提供更强的类型化功能、编译时检查和改进的调试器支持。
如何使用LINQ查询?
所有的LINQ查询操作都可以由三个不同的操作组成:
1、获取数据源。
2、创建查询。
3、执行查询。
数据源可以为任意可查询类型,即支持IEnumerable或IEnumerable 接口及其派生接口的类型。
int[] numbers = new int[7]{0,1,2,3,4,5,6};
var numQuery =
from num in numbers
where (num % 2) == 0
select num;
foreach(int num in numQuery)
{
console.Write("{0,1} ",num);
}
上例实现从一个int数组中检索出所有偶数。其中数据源为numbers数组。
该查询表达式包含三个子句(如果对SQL熟悉,则不会陌生,但是语句顺序是不一样的):from、where和select。from 子句指定数据源,where 子句应用筛选器,select 子句指定返回的元素类型。
注意,var numQuery =...语句只是构建一个查询表达式,执行时并不会立即检索数据,当执行到下面的foreach语句时,才会检索数据。
当然,并不是必须使用foreach才能检索出结果,这个是可控的:
对于聚合函数如Count、Max、Average、First等,这些查询仅仅返回单个值而非集合,此时就不用使用foreach来检索结果了:
var numQuery =
from num in numbers
where (num % 2) == 0
select num;
int numCount = numQuery.Count();
也可以强制立即执行查询结果并缓存,可调用ToList 或ToArray 方法:
List numQuery =
(from num in numbers
where (num % 2) == 0
select num).ToList();
关于var
在C#中并没有"变体"变量的说法,即所有的变量都必须在申明时指定变量类型,var意义上并非JavaScript中的var,但也不代表一种确切的类型。在C#中var表示一种推断"类型",它指示编译器根据初始化语句右侧的表达式推断变量的类型。推断的类型可以是内置类型、匿名类型、用户定义类型、.NET Framework类库中定义的类型或任何表达式。即,var是一种简化写法,在程序编译时,编译器自动将var关键字替换成正确的类型:
var s = "Hello"; //var编译成string类型
var a = new[] {0,1,2}; //var编译成int[]
而上例中的var numQuery 将被编译成IEnumberable 。
以上仅对LINQ查询做简单介绍,实际上LINQ与SQL一样是复杂灵活的,同样可实现SQL的排序、分组等基本功能,读者如有兴趣深入了解,请参照MSDN。
如何创建XML树?
LINQ to XML 为创建XML元素提供了一种称为"函数构造"(即指在单个语句中创建XML树)的有效方式。
XElement类可实现XML树的构造,其构造函数可以对内容采用多中类型的参数。例如,可以传递一个XElement对象,该对象将成为一个子元素。可以传递一个XAttribute对象,该对象将成为一个元素的属性。也可以传递任何其他类型对象,该对象将转换成字符串并成为该元素的内容。
XElement类构造函数可采用Object的参数数组,由此可以一次性地传递任意数目的对象。这可以方便地构造出复杂内容的元素。如果参数中的对象实现了IEnumerable ,则枚举对象中的集合,并添加集合中的所有项。如果集合包含XElement或XAttribute对象,则单独添加集合中的每一项。这表示你可以直接使用LINQ查询的结果来构造新的XML树。
XElement contacts =
new XElement("Contacts",
new XElement("Contact",
new XElement("Name", "Patrick Hines"),
new XElement("Phone", "206-555-0144"),
new XElement("Address",
new XElement("Street1", "123 Main St"),
new XElement("City", "Mercer Island"),
new XElement("State", "WA"),
new XElement("Postal", "68042")
)
)
);
上例XML结果:
Patrick Hines
206-555-0144
123 Main St
Mercer Island
WA
68042
下例将使用LINQ的查询结果来构建XML树:
XElement srcTree =
new XElement("Root",
new XElement("Element", 1),
new XElement("Element", 2),
new XElement("Element", 3),
new XElement("Element", 4),
new XElement("Element", 5)
);
XElement xmlTree =
new XElement("Root",
new XElement("Child", 1),
new XElement("Child", 2),
from el in srcTree.Elements()
where (int)el > 2
select el
);
Console.WriteLine(xmlTree);
结果:
1
2
3
4
5
克隆还是附加?
在将XNode(包括XElement)或XAttribute对象添加到新树时,如果新内容没有父级,则直接将这些对象附加到XML树中。如果新内容已经有父级,并且是另一XML树的一部分,则克隆新内容,并将新克隆的内容附加到XML树。
XElement xmlTree1 = new XElement("Root",
new XElement("Child1", 1)
);
XElement child2 = new XElement("Child2", 2);
XElement xmlTree2 = new XElement("Root",
xmlTree1.Element("Child1"),
child2
);
上例,xmlTree2树中,由于Child1属于xmlTree1树,固添加到xmlTree2时为克隆方式,即如果后续修改树1的此节点,树2中的节点不会变化。而child2添加到树2的时候采用的是附加方式,即后续程序修改了变量child2,那么对应的树2节点也会发生变化。
待续...