基本的LINQ操作
LINQ to Object:
LINQ(语言集成查询):一种强类型查询语言。可以用于多种数据库存储,甚至与关系数据库完全无关的存储。
实质:LINQ查询操作符是调用System.Linq.Enumerable类中的方法的一种简便形式,c#编译器将所有的LINQ操作都翻译为
对Enumerable类中方法的调用,因此大多数情况下linq查询的返回值为实现了Ienumerable<T>接口的类型
延迟执行:我们在迭代LINQ查询内容之前,LINQ查询并没有真正的执行而是在迭代数据项时运行
int[] nums = { 10, 15, 8, 7, 5, 6, 9 };
//linq查询获得小于10的数
var result = from n in nums where n < 10 select n;foreach (var item in result)
{
Console.WriteLine("{0}<10",item);
}
Console.WriteLine();
//修改发生在LINQ查询之后
nums[0] = 1;
//遍历LINQ结果内容,会发现修改起作用了
foreach (var item in result)
{
Console.WriteLine("{0}<10", item);
}
立即执行:Enumerable定义了如ToArray<T>()、ToList<T>等扩展方法.当LINQ查询使用这些方法时便会产生数据快照。然后就可以对这些快照数据进行独立的操作了
int[] nums = { 10, 15, 8, 7, 5, 6, 9 };
//linq查询获得小于10的数,使用ToArray<int>()方法获得数据快照,返回int[]数组
int[] result = (from n in nums where n < 10 select n).ToArray<int>();foreach (int item in result)
{
Console.WriteLine("{0}<10",item);
}
Console.WriteLine();
//修改发生在LINQ查询之后
nums[0] = 1;
//遍历LINQ结果内容,此时修改不会更改result的结果
foreach (var item in result)
{
Console.WriteLine("{0}<10", item);
}
对非泛型集合使用LINQ查询:linq查询是基于IEnumerable<T>接口的,如果要实现非泛型的LINQ查询则需要使用
Enumerable.OfType<T>()方法进行转换
1.使用Enumerable.OfType<T>()方法进行转换
//非泛型的学生集合
ArrayList student = new ArrayList()
{
new Student {StuNo=1,StuName="rock",Age=18,StuClasses=1 },
new Student { StuNo=2,StuName="jason",Age=19,StuClasses=1},
new Student { StuNo=3,StuName="FL",Age=18,StuClasses=1}
};
//把ArrayList转换成一个兼容于IEnumerable<T>的类型
var students = student.OfType<Student>();
//建立兼容类型的查询表达式
var bigStudents = from s in students where s.Age > 18 select s;foreach (var item in bigStudents)
{
Console.WriteLine("{0} age is biger than other",item.StuName);
}
2.使用OfType<T>()筛选数据:过滤出那些类型不同于迭代操作中所指定类型的元素(基于类型的筛选)
static void OfTypeAsFilter()
{
ArrayList myStuff=new ArrayList();
myStuff.AddRange(new Object[] {10,400,8,false,"stringname"});
//筛选出myStuff中的整数
var Ints=myStuff.OfType<int>();
//此时会输出10 400 8
foreach(int i in Ints)
{
Console.WriteLine("Int Value : {0}",i);
}
}
C#LINQ查询操作符
1.基本的选择语法:
//in 后面的数据容器可以是数组,集合或XML文档
var result= from matchingItem in container select machingItem;
2.获取数据子集:
//where 后面是结果为布尔值得表达式,可以是任意合法的C#语句表达式
var result=from item in container where BoolenExpression select item
例:
var bigStudents = from s in students where s.Age > 18 && s.StuNo==2 select s;
3.使用Enumerable获取总数(聚合操作):使用扩展方法Count(); 额外的聚合操作还有Average()、Max()、Min()、Sum()
如:
int sum = (from s in students where s.Age > 18 && s.StuNo == 2 select s).Count();
4.对表达式进行排序:
如:
var bigStudents = from s in students where s.Age == 18 orderby s.StuName descending/asending select s;
5.维恩图工具:Enumerable类提供了一些扩展方法可以对两个或多个LINQ查询的数据进行合并(union)、比较(difference)和交叉(intersection)
a.Except(),返回包含两个容器的不同的结果集:
List<string> myColor = new List<string> { "black", "red", "green" };
List<string> yourColor = new List<string> { "black", "gray", "green" };var colorDiff = (from c in myColor select c).Except(from c in yourColor select c);
Console.WriteLine("the difference :");
foreach (string item in colorDiff)
{
Console.WriteLine(item);
}
b.Intersect():返回两个容器共同项
var colorCommon = (from c in myColor select c).Intersect(from c in yourColor select c);
c.Union():返回多个LINQ查询的所有成员,不包含重复项
var colorAll = (from c in myColor select c).Union(from c in yourColor select c);
d.Concat():返回多个LINQ查询的所有成员,包含重复项
var colorAlls = (from c in myColor select c).Concat(from c in yourColor select c);
6.移除重复:Concat()方法返回的成员包含重复项,可以调用Distinct()方法去重
foreach(string s in colorAlls.Distinct()) { Console.WriteLine(s);}
使用Enumerable类型和Lambda表达式来建立查询表达式(方法查询语法)
string[] names = { "Rock", "Zed H", "Jason", "Mr H" };
//方法查询语法,Enumerable类扩展方法参数为委托,此处使用Lambda表达式
var name = names.Where(n => n.Contains(" ")).OrderBy(n => n).Select(n => n);
foreach (var item in name)
{
Console.WriteLine(item);
}
LINQ to XML
传统的XML API:通过使用System.Xml程序集中的类和方法来操作XML
public static void BuildXmlDocWithDOM()
{
XmlDocument doc = new XmlDocument(); //在内存中新建一个Xml文档
XmlElement School = doc.CreateElement("School"); //用元素<School>填充文档
//创建一个<student>子元素,它包含一个Major特性
XmlElement student = doc.CreateElement("Student");
student.SetAttribute("Major", "IT");
//创建<student>元素中的数据
XmlElement name = doc.CreateElement("StuName");
name.InnerText = "Rock";
XmlElement number = doc.CreateElement("StuNo");
number.InnerText = "007";
//将<StuName> <StuNo>元素添加到<student>元素
student.AppendChild(name);
student.AppendChild(number);
//将<student>元素添加到<School>元素
School.AppendChild(student);//将完整的XML插入到XmlDocument对象并保存文件
doc.AppendChild(School);
doc.Save("school.xml");
}
LINQ to XML :不必使用一组函数来更新XML树,只需要编写自上而下的代码就可以了(如下)
public static void BuildXmlDocWithLINQ()
{
XDocument inventoryDoc = new XDocument(
new XDocument(
new XDeclaration("1.0", "utf-8", "yes"), //XML文档公开声明
new XComment("Students Information!"), //XML文档注释
new XElement("School",new XAttribute("Name","Tyut"), //每一个特定元素都可以有固有的特性元素
new XElement("Student", new XAttribute("Major", "IT"),
new XElement("StuName",new XAttribute("From","ChiFeng"), "Rock"),
new XElement("StuNo", "007"))
)
)
);inventoryDoc.Save("newschool.xml");
}
常用Linq成员及其意义:
XAttribute 表示一个XML元素特性
XCData 表示XML文档中的CDATA部分
XComment 表示一个XML注释
XDeclaration 表示一个XML文档的公开声明
XDocument 表示一个XML文档的全部内容
XElement 表示一个XML文档的特定元素包括根元素
XName 表示一个XML元素或XML特性的名称
XNamespace 表示一个XML命名空间
加载和解析XML内容:XElement和XDocument都支持Load()和Parse()方法,可以从包含XML数据的string对象或外部XML文件获取
XML对象模型。
string myElent =
@"<Car ID='3'>
<Color>Yellow</Color>
<Make>Yugo</Make>
</Car>";
XElement newElement = XElement.Parse(myElent); //获取string对象XML模型
XDocument myDoc = XDocument.Load("Inventory.xml"); //获取外部XML模型
常用LINQ to XML的轴方法:
Descendants<T> 返回经过筛选的元素集合,其中包含元集合中每个元素和文档的子元素
string data = string.Empty;
XDocument myDoc = XDocument.Load("newschool.xml");
var makeInfo = from car in myDoc.Descendants("Student") //筛选<Student>元素节点下的所有子元素
select car;
foreach (var item in makeInfo)
{
data += string.Format("-->{0}\n", item);
}
Console.WriteLine(data);
输出结果如下:
<Student Major="IT">
<StuName From="ChiFeng">Rock</StuName>
<StuNo>007</StuNo>
</Student>
Attributes() 返回源集合中经过筛选的每个元素的特性的集合
var makeInfo = from stu in myDoc.Descendants("Student").Attributes()
select stu;
Remove() 将源集合中的每个特性从其父节点中移除
XDocument myDoc = XDocument.Load("newschool.xml");
myDoc.Descendants("StuNo").Remove();
Add() 增加节点
XElement newElement = new XElement("StuNo", "007");
myDoc.Descendants("Student").First().Add(newElement) //在Student元素下新增一个节点