本文是Linq使用系列教程中的第一部。
- 查询对象为IEnumerable<T>或IQueryable<T>类型;
- 查询返回结果同样为IEnumerable<T>或IQueryable<T>类型。
Linq 分为:Linq to objects、Linq to DataSets、Linq to SQL、Linq to Entities、Linq to XML五类。
简单使用
类型 查询变量 = from 临时变量 in 集合对象或数据库对象 [where 条件表达式] [order by 条件] select 临时变量或临时变量中被查询的值 [group by]
① 普通查询:
// 数据源 int[] arr = new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; // Linq查询 var result = from item in arr // 声明临时变量item,并说明其为数组arr中的元素,item where item > 4 select item; // 将查询结果(item)添加到result中 // 遍历Linq查询结果,实际上是“Linq查询”是伴随foreach执行的,即在foreach执行前“Linq查询”不会执行 foreach(int i in result) { Console.Write(i); //输出56789 }
② 查询并排序:
int[] arr = new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; var result = from item in arr where item > 4 orderby item descending // 降序排列 select item; foreach(int i in result) { Console.Write(i); // 输出:98765 }
③ 类型转换:
int[] arr = new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; var result = from item in arr where item > 4 select string.Format("值:{0} ", item); // 转化为String类型,并格式化 foreach(string i in result) { // 变量i更改为string类型 Console.Write(i); // 输出“值:5 值:6 值:7 值:8 值:8 ” }
④ 查询单一值:
int[] arr = new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; int result0 = (from item in arr where item > 4 select item).Count(); // 整个语句被一堆()抱起来,统计数目 int result1 = (from item in arr where item > 4 select item).Max(); // 查询最大值 Console.WriteLine(result0); //输出:5 Console.WriteLine(result1); //输出:9
from子查询
class Program { static void Main(string[] args) { // 创建一个类似二维数组的泛型变量arr,用于存储学生信息 List arr = new List { new Student {name = "李宁", scores = new List{11, 12, 34} }, new Student {name = "阿迪", scores = new List{11, 16, 34} }, new Student {name = "耐克", scores = new List{18, 12} }, }; // 查询学生分数大于15分的记录 var result = from stu in arr // 声明临时变量stu from sc in stu.scores // 声明临时变量sc用于“子查询”, where sc > 15 select new {name = stu.name, score = sc}; // 将查询结果“投影”到一个新的对象中,该对象有name和score两个属性。 foreach (var s in result) { Console.WriteLine(s.name + ":" + s.score); } } } class Student { public string name; // 学生姓名 public List scores; // 学生分数,一个学生可以有多个分数 }
输出结果:
李宁:34
阿迪:16
阿迪:34
耐克:18
李宁:34
阿迪:16
阿迪:34
耐克:18
上述示例,实际是每个学生都与其分数做了多次关联,并将查询结果存入新的对象(new {...})中。
关联多个数据源
// 定义数据源 char[] upper = { 'A', 'B', 'C' }; char[] lower = { 'x', 'y', 'z' }; // 关联两个数据源 var result0 = from up in upper from lo in lower select new {upper = up, lower=lo}; foreach (var item in result0) { Console.WriteLine(item.upper + " " + item.lower); } // 关联两个数据源,并按条件筛选 var result1 = from up in upper from lo in lower where up != 'B' select new { upper = up, lower = lo }; foreach (var item in result1) { Console.WriteLine(item.upper + " " + item.lower); }
两次输出结果分别为:
分组
① 简单分组
class Program { static void Main(string[] args) { // 定义数据源 List<Product> arr = new List<Product> { new Product{name = "衬衫", price = 13.9m, cid = 1}, new Product{name = "短裤", price = 199.2m, cid = 1}, new Product{name = "奥迪", price = 1.6m, cid = 2}, new Product{name = "奔驰", price = 2.7m, cid = 2}, new Product{name = "歼十", price = 82.3m, cid = 3}, new Product{name = "播音", price = 91.3m, cid = 3}, }; var result = from p in arr group p by p.cid; // 遍历组别 foreach (var gp in result) { Console.WriteLine("=============="); // 遍历每组成员 foreach (var pd in gp) { Console.WriteLine("{0}-{1}-{2}", pd.name, pd.price, pd.cid); } } Console.Read(); } } class Product { public string name; // 商品名称 public decimal price; // 商品价格 public int cid; // 商品分类 }
此处的分组并非SQL中的分组,SQL中的分组主要用于分组统计。而此处的分组是将原来“一维的数据”按照一定规则分组成“二维的数据”,其输出结果:
② 对组对象处理
static void Main(string[] args)
{
// 定义数据源
List arr = new List
{
new Product{name = "衬衫", price = 13.9m, cid = 1},
new Product{name = "短裤", price = 199.2m, cid = 1},
new Product{name = "奥迪", price = 1.6m, cid = 2},
new Product{name = "奔驰", price = 2.7m, cid = 2},
new Product{name = "歼十", price = 82.3m, cid = 3},
new Product{name = "播音", price = 91.3m, cid = 3},
};
List classList = new List
{
new Pclass{cname="衣服", cid = 1},
new Pclass{cname="汽车", cid = 2},
new Pclass{cname="飞机", cid = 3},
};
var result =
from p in arr
// G实际上就是组,格式为<Vey, Values>格式
// Key为该分组的cid
// Values为该组元素集合
group p by p.cid into G
from cls in classList
where G.Key == cls.cid // 关联组G和classList集合
select new {cname = cls.cname, cid = cls.cid, gplist = G};
foreach (var gp in result)
{
Console.WriteLine();
Console.WriteLine("组名:{0},分类id:", gp.cname, gp.cid);
foreach (var pd in gp.gplist)
{
Console.WriteLine("{0}-{1}-{2}", pd.name, pd.price, pd.cid);
}
}
}
}
class Pclass
{
public int cid; // 分类id
public string cname; // 分类名称
}
class Product
{
public string name; // 商品名称
public decimal price; // 商品价格
public int cid; // 商品分类
}
上述代码的关键在于对“into G”的理解,查询部分的执行过程为:
第一步执行分组,分出一个组(如cid=1组)后存入临时变量G中;然后执行第二步,将该分组G与classList集合关联,将符合条件的结果按照select指定格式存储。第一个分组处理完毕后,按照上述步骤处理第二个分组(cid=2),依次类推。
程序执行输出结果:
③对分组对象进行删除
static void Main(string[] args) { List sts = new List { new Student{id= 1, name="李宁", cid = 1}, new Student{id= 2, name="李娜", cid = 2}, new Student{id= 3, name="耐克", cid = 3}, new Student{id= 4, name="阿迪", cid = 2}, new Student{id= 5, name="奔驰", cid = 1}, new Student{id= 6, name="报名", cid = 3}, }; var result = from s in sts group s by s.cid into G select new { id = G.Key, list = ( // 排除id为偶数的学生 from m in G where (m.id % 2 != 0) select m ) }; foreach (var item in result) { Console.WriteLine("Cid:{0}", item.id); foreach (var s in item.list) { Console.WriteLine("{0}-{1}-{2}", s.id, s.name, s.cid); } } }
let 子句
用于在查询中创建一个新的临时变量
static void Main(string[] args) { // 定义数据源 List sts = new List { new Student{id= 1, name="李宁", cid = 1}, new Student{id= 2, name="李娜", cid = 2}, new Student{id= 3, name="耐克", cid = 3}, new Student{id= 4, name="阿迪", cid = 2}, new Student{id= 5, name="奔驰", cid = 1}, new Student{id= 6, name="报名", cid = 3}, }; var result = from s in sts let fullname = s.id + s.name select string.Format("id:{0},全称:{1}", s.id, fullname); foreach (string i in result) { Console.WriteLine(i); } }
声明:如需转载,请注明来源于www.webym.net并保留原文链接:http://www.webym.net/jiaocheng/766.html