任县网站建设价格信息,渠道网关,域名除了做网站还能做什么,网站托管服务目录
六、连表操作符 1、内连接2、左外连接(DefaultIfEmpty)3、组连接七、集合操作 八、分区操作符 1、Take()#xff1a;2、TakeWhile()#xff1a;3、Skip()#xff1a;4、SkipWhile()#xff1a;九、聚合操作符 1、Count#xff1a; 返回集合项数。 2、LongCount2、TakeWhile()3、Skip()4、SkipWhile()九、聚合操作符 1、Count 返回集合项数。 2、LongCount返回一个 System.Int64表示序列中的元素的总数量。3、Sum 序列中的所有数字的和。4、Min 返回集合中的最小值。5、Max 返回集合中的最大值。6、Average 返回集合中的平均值。7、Aggregate 传递一个 lambda 表达式该表达式对所有的值进行聚合。十、转换操作符 1) Cast2) ToArray3) ToList4) ToDictionary5) ToLookup6) DefaultIfEmpty7) AsEnumerable十一、生成操作符 1) Empty2) Range3) Repeat十二、量词操作符 1) Any2) All3) Contains十三、元素操作符 十四、并行查询并行Linq 十五、分区器 十六、取消 六、连表操作符 1、内连接
1、使用 join 子句 根据特定的条件合并两个数据源但之前要获得两个要连接的列表。
业务说明返回1958到1965年间的车手冠军和车队冠军信息根据年份关联
? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 var racers from r in Formula1.GetChampions() from y in r.Years select new { Year y, Name r.FirstName r.LastName }; var teams from t in Formula1.GetContructorChampions() from y in t.Years select new { Year y, Name t.Name }; var racersAndTeams0 (from r in racers join t in teams on r.Year equals t.Year orderby t.Year select new { Year r.Year, Racer r.Name, Team t.Name }).Take(10);
方法语法
? 1 2 3 var racersAndTeams racers .Join(teams, r gt; r.Year, t gt; t.Year, (r, t) gt; new { Year r.Year, Racer r.Name, Team t.Name }) .OrderBy(p gt; p.Year).Take(10);
结果 Year Champion Constructor Title 1958: Mike Hawthorn Vanwall 1959: Jack Brabham Cooper 1960: Jack Brabham Cooper 1961: Phil Hill Ferrari 1962: Graham Hill BRM 1963: Jim Clark Lotus 1964: John Surtees Ferrari 1965: Jim Clark Lotus 1966: Jack Brabham Brabham 1967: Denny Hulme Brabham 2、或者合并成一个LINQ 查询
? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 var racersAndTeams (from r in from r1 in Formula1.GetChampions() from yr in r1.Years select new { Year yr, Name r1.FirstName r1.LastName } join t in from t1 in Formula1.GetContructorChampions() from yt in t1.Years select new { Year yt, Name t1.Name } on r.Year equals t.Year orderby t.Year select new { Year r.Year, Racer r.Name, Team t.Name }).Take(10);
方法语法
? 1 2 3 4 5 6 7 8 9 10 11 12 var racersAndTeams0 Formula1.GetChampions() .SelectMany(m gt; m.Years, (m, y) gt; new { Racer m, Year y }) .Join(Formula1.GetContructorChampions() .SelectMany(m gt; m.Years, (m, y) gt; new { Team m, Year y }) , m gt; m.Year, m1 gt; m1.Year , (m, m1) gt; new { Year m.Year, Racer m.Racer.FirstName m.Racer.LastName, Team m1.Team.Name }) .OrderBy(m gt; m.Year).Take(10); 2、左外连接(DefaultIfEmpty)
左外连接返回左边序列中的全部元素即使它们在右边的序列中并没有匹配的元素。
左外连接用join子句和 DefaultIfEmpty 方法定义。 使用 DefaultIfEmpty 定义其右侧的默认值。
linq只支持左连接如要右连接将query和query1调换位置
业务说明如赛车手比车队设立冠军的年份要早可能某个年份只有赛车手冠军没有车队冠军这时候需要左连接查询。
? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 var racers from r in Formula1.GetChampions() from y in r.Years select new { Year y, Name r.FirstName r.LastName }; var teams from t in Formula1.GetContructorChampions() from y in t.Years select new { Year y, Name t.Name }; var racersAndTeams (from r in racers ?? join t in teams on r.Year equals t.Year into rt
? 1 2 3 4 5 6 7 8 9 10 11 12 13 from t in rt.DefaultIfEmpty() orderby r.Year select new { Year r.Year, Champion r.Name, Constructor t null ? no constructor championship : t.Name }).Take(10); foreach (var item in racersAndTeams) { Console.WriteLine({0}: {1,-20} {2}, item.Year, item.Champion, item.Constructor); }
结果 1950: Nino Farina no constructor championship 1951: Juan Manuel Fangio no constructor championship 1952: Alberto Ascari no constructor championship 1953: Alberto Ascari no constructor championship 1954: Juan Manuel Fangio no constructor championship 1955: Juan Manuel Fangio no constructor championship 1956: Juan Manuel Fangio no constructor championship 1957: Juan Manuel Fangio no constructor championship 1958: Mike Hawthorn Vanwall 1959: Jack Brabham Cooper 3、组连接
左外连接使用了组连接和 into 子句。它有一部分与组连接相同只不过组连接不适用 DefaultIfEmpty 方法。
使用组连接时基于键相等对两个两个独立的序列的元素进行关联并对结果进行分组。
常应用于返回“主键对象-外键对象集合”形式的查询。
业务说明返回1958到1965年间的车手冠军和车队冠军信息根据年份关联并分组
注意直接出现在join子句之后的into关键字会被翻译为GroupJoin而在select或group子句之后的into表示继续一个查询。
? 1 2 3 4 5 6 7 8 9 // 查询表达式 var racersAndTeams ( from r in racers join t in teams on r.Year equals t.Year into groupTeams select new { Year r.Year, Racer r.Name, GroupTeams groupTeams }).Take(10);
方法语法
? 1 2 3 4 5 6 7 8 var racersAndTeams1 racers .GroupJoin(teams, r gt; r.Year, t gt; t.Year, (r, t) gt; new { Year r.Year, Racer r.Name, GroupTeams t } ).Take(10);; foreach (var item in racersAndTeams) { Console.WriteLine({0}: {1,-20} {2}, item.Year, item.Racer, item.GroupTeams.Count()); }
结果 1950: Nino Farina 0 1952: Alberto Ascari 0 1953: Alberto Ascari 0 1951: Juan Manuel Fangio 0 1954: Juan Manuel Fangio 0 1955: Juan Manuel Fangio 0 1956: Juan Manuel Fangio 0 1957: Juan Manuel Fangio 0 1958: Mike Hawthorn 1 1961: Phil Hill 1 2、join…on…equals…支持多个键关联可以使用匿名类型来对多个键值进行Join如下所示
? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 // 查询表达式 var query17 from r in racers join r2 in teams on new { Name r.Name.Substring(0, 1), Year r.Year } equals new { Name r2.Name.Substring(0, 1), Year r2.Year } into yearResults select new { Results yearResults }; foreach (var item in query17) { foreach (var info in item.Results) { Console.WriteLine(info.Name); } } //McLaren 七、集合操作
集合操作通过调用实体类的 GetHashCode() 和 Equals() 方法比较对象。 对于自定义比较可以传递实现 IEqualityComparer接口的对象。
业务说明获取使用车型”Ferrari”和车型”Mclaren”都获得过车手冠军车手列表
? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 void Main() { Funclt;string, IEnumerablelt;Racergt;gt; racersByCar car gt; from r in Formula1.GetChampions() from c in r.Cars where c car orderby r.LastName select r; foreach (var racer in racersByCar(Ferrari).Intersect(racersByCar(McLaren), new RacerComparer())) { Console.WriteLine(racer); } } public class RacerComparer : IEqualityComparerlt;Racergt; { public bool Equals(Racer x, Racer y) { if (Object.ReferenceEquals(x, y)) return true; return x ! null amp;amp; y ! null amp;amp; x.FirstName y.FirstName amp;amp; x.LastName y.LastName; } public int GetHashCode(Racer obj) { int hashStudentId obj.FirstName.GetHashCode(); int hashScore obj.LastName.GetHashCode(); return hashStudentId ^ hashScore; } }
结果 Niki Lauda 1) Union并集返回两个序列的并集去掉重复元素。2) Concat连接返回两个序列的并集。3) Intersect交集返回两个序列中都有的元素即交集。4) Except差集返回只出现在一个序列中的元素即差集。
示例合并html开始标签和结束标签
? 1 2 3 4 5 var letters new string[] { A, B, C, D, E }; var numbers new int[] { 1, 2, 3 }; var q letters.Zip(numbers, (l, n) gt; l n.ToString()); foreach (var s in q) Console.WriteLine(s);
结果 A1 B2 C3 5) Zip通过使用指定的委托函数合并两个序列集合的总个数不变。
示例
? 1 2 3 4 5 6 7 int[] arr1 { 1, 4, 7, 9 }; int[] arr2 { 1, 7, 9, 4 }; Console.WriteLine(排序前 是否相等{0} , arr1.SequenceEqual(arr2) ? 是 : 否); // 否 Console.WriteLine(); Console.WriteLine(排序后 是否相等{0} , arr1.SequenceEqual(arr2.OrderBy(k gt; k)) ? 是 : 否); // 是
6) SequenceEqual判断两个序列是否相等需要内容及顺序都相等。 八、分区操作符
扩展方法 Take() 和 Skip() 等的分区操作可以用于分页。
添加在查询的“最后”返回集合的一个子集。 1、Take()
从序列的开头返回指定数量的连续元素。 2、TakeWhile()
只要满足指定的条件就会返回序列的元素。
从第一个元素开始, 读取Starts小于40的人员列表只要遇到大于40的元素就立即停止返回。
? 1 2 3 4 5 6 7 8 9 10 var racers (from r in Formula1.GetChampions() orderby r.Starts select r ) strong.TakeWhile(p /strongstronggt; p.Starts lt; 40/strongstrong);/strong foreach (var name in racers) { Console.WriteLine(${name:A}); }
结果 Alberto Ascari, Italy; starts: 32, wins: 10 Nino Farina, Italy; starts: 33, wins: 5 3、Skip()
跳过序列中指定数量的元素然后返回剩余的元素。
业务说明将车手冠军列表按每页5个名字进行分页。
? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 int pageSize 5; int numberPages (int)Math.Ceiling(Formula1.GetChampions().Count() / (double)pageSize); for (int page 0; page lt; numberPages; page) { Console.WriteLine(Page {0}, page); var racers ( from r in Formula1.GetChampions() orderby r.LastName select r.FirstName r.LastName ) .Skip(page * pageSize).Take(pageSize); foreach (var name in racers) { Console.WriteLine(name); } }
结果 Page 0 Fernando Alonso Mario Andretti Alberto Ascari Jack Brabham Jim Clark Page 1 Juan Manuel Fangio Nino Farina Emerson Fittipaldi Mika Hakkinen Mike Hawthorn 4、SkipWhile()
只要满足指定的条件就跳过序列中的元素然后返回剩余元素。 九、聚合操作符
聚合操作符返回一个值。 1、Count 返回集合项数。 2、LongCount返回一个 System.Int64表示序列中的元素的总数量。
业务说明下面的Count 方法只返回获得冠军次数超过三次的赛车手因为同一个查询中需要使用同一个计数超过一次所以使用let 子句定义了一个变量 numberYear.
? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 var query from r in Formula1.GetChampions() let numberYears r.Years.Count() where numberYears gt; 3 orderby numberYears descending, r.LastName select new { Name r.FirstName r.LastName, TimesChampion numberYears }; foreach (var r in query) { Console.WriteLine({0} {1}, r.Name, r.TimesChampion); } //Michael Schumacher 7 //Juan Manuel Fangio 5 //Alain Prost 4 //Jack Brabham 3 //Niki Lauda 3 //Nelson Piquet 3 //Ayrton Senna 3 //Jackie Stewart 3 3、Sum 序列中的所有数字的和。
业务说明下面的Sum 方法用于计算一个国家赢得比赛的总次数。
首先根据国家对赛车手分组再在新创建的匿名类型中把Wins 属性赋予某个国家赢得比赛的总次数。
? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 var countries (from c in from r in Formula1.GetChampions() group r by r.Country into c select new { Country c.Key, Wins (from r1 in c select r1.Wins).Sum() } orderby c.Wins descending, c.Country select c).Take(5); foreach (var country in countries) { Console.WriteLine({0} {1}, country.Country, country.Wins); } //UK 138 //Germany 91 //Brazil 78 //France 51 //Finland 40 4、Min 返回集合中的最小值。 5、Max 返回集合中的最大值。 6、Average 返回集合中的平均值。 7、Aggregate 传递一个 lambda 表达式该表达式对所有的值进行聚合。
业务说明Aggregate的 第一个参数是算法的种子即初始值。可选 第二个参数是一个表达式用来对每个元素进行计算委托第一个参数是累加变量第二个参数当前项。 第三个参数是一个表达式用来对最终结果进行数据转换。
? 1 2 3 4 int[] numbers { 1, 2, 3 }; int y numbers.Aggregate((tol, n) gt; prod n); // 123 6 int x numbers.Aggregate(0, (tol, n) gt; tol n); // 0123 6 int z numbers.Aggregate(0, (tol, n) gt; tol n, r gt; r * 2);// 0123*2 12 十、转换操作符
查询可以推迟到访问数据项时再执行。在迭代中使用查询时查询会执行。
而使用转换操作符会立即执行查询把查询结果放在数组、列表或字典中。
LINQ本身支持四种不同的集合生成方式包含生成数组的ToArray()、生成列表的ToList、生成字典集合的ToDictionary 以及生成Lookuptkey,telement类的ToLookup。 1) Cast
将非泛型的 IEnumerable 集合元素转换为指定的泛型类型若类型转换失败则抛出异常。 如果需要在非类型化的集合上如ArrayList使用LINQ 查询就可以使用Cast 方法。
在下面的例子中基于Object类型的ArrayList集合用Racer对象填充。 ? 1 2 3 4 5 6 7 8 9 10 11 12 var list new ArrayList(Formula1.GetChampions() as System.Collections.ICollection); var query from r in list.Cast() where r.Country USA orderby r.Wins descending select r; foreach (var racer in query) { Console.WriteLine({0:A}, racer); } //Mario Andretti, USA; starts: 128, wins: 12 //Phil Hill, USA; starts: 48, wins: 3 2) ToArray
从 IEnumerable 创建一个数组。 3) ToList
立即执行查询,从 IEnumerable 创建一个 List。 4) ToDictionary
根据指定的键选择器函数从 IEnumerable 创建一个 Dictionarytkey,tvalue。
将列表转换为字典
? 1 2 3 4 5 6 7 8 9 10 11 var spartans new Listlt;dynamicgt; { new {OpponentUAB,Score55-18}, new {OpponentBowling Green,Score55-18}, new {OpponentPittsburgh,Score55-18}, new {OpponentNotre Dame,Score55-18} }; //字典是一种键值对的集合ToDictionary 将一个IEnumerablelt;Tgt;对象比如LINQ查询所返回的结果 //转换为一个IDictionarylt;Key,Valuegt;对象。 IDictionarylt;string, dynamicgt; stats spartans.ToDictionary(key gt; (string)key.Opponent); Console.WriteLine(Spartans vs. {0} {1}, stats[Notre Dame].Opponent, stats[Notre Dame].Score); 5) ToLookup
根据指定的键选择器函数从 IEnumerable 创建一个 System.Linq.Lookup。 ToLookup使用比较复杂Lookup类似于Dictionary不过Dictionary每个键只对应一个值而Lookup则是1n 的映射。 Lookup没有公共构造函数而且是不可变的。在创建Lookup之后不能添加或删除其中的元素或键。可以将ToLookup 视为GroupBy与ToDictionary的功能合体 业务说明将车手冠军按其使用车型进行分组并显示使用”williams”车型的车手名字。
? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 ILookuplt;string, Racergt; racers (from r in Formula1.GetChampions() from c in r.Cars //使用复合的from 查询 select new { Car c, Racer r } ).ToLookup(cr gt; cr.Car, cr gt; cr.Racer); if (racers.Contains(Williams)) { foreach (var williamsRacer in racers[Williams]) { Console.WriteLine(williamsRacer); } } //Alan Jones //Keke Rosberg //Nelson Piquet //Nigel Mansell //Alain Prost //Damon Hill //Jacques Villeneuve 6) DefaultIfEmpty
返回指定序列的元素如果序列为空则返回包含类型参数的默认值的单一元素集合 。
? 1 2 3 var defaultArrCount (new int[0]).DefaultIfEmpty().Count(); Console.WriteLine(defaultArrCount); //1 7) AsEnumerable
返回类型为 IEnumerable 。用于处理LINQ to Entities操作远程数据源与本地集合的协作 十一、生成操作符
生成操作符返回一个新的集合。三个生成操作符不是扩展方法而是返回序列的正常静态方法。 1) Empty
生成一个具有指定类型参数的空序列 IEnumerable。 Empty() 方法返回一个不返回值的迭代器用于需要一个集合的参数可以给参数传递空集合。
? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 string[] names1 { Hartono, Tommy }; string[] names2 { Adams, Terry, Andersen, Henriette Thaulow, Hedlund, Magnus, Ito, Shu }; string[] names3 { Solanki, Ajay, Hoeing, Helge, Andersen, Henriette Thaulow, Potra, Cristina, Iallo, Lucio }; Listlt;string[]gt; namesList new Listlt;string[]gt; { names1, names2, names3 }; IEnumerablelt;stringgt; allNames namesList.Aggregate(Enumerable.Emptylt;stringgt;(), (current, next) gt; next.Length gt; 3 ? current.Union(next) : current); foreach (string name in allNames) { Console.WriteLine(name); } //Adams, Terry //Andersen, Henriette Thaulow //Hedlund, Magnus //Ito, Shu //Solanki, Ajay //Hoeing, Helge //Potra, Cristina //Iallo, Lucio 2) Range
生成指定范围内的整数的序列 IEnumerable。 如需要填充一二范围的数字此时就应使用 Range() 方法。这个方法第一个参数作为起始值把第二个参数作为要填充的项数。
? 1 2 3 4 5 6 7 var values Enumerable.Range(1, 20); foreach (var value in values) { Console.WriteLine(value); } // 结果 1 2 3 4 5 6 ...... 19 20
Range() 方法不返回填充所定义值的集合与其他方法一样推迟查询返回一个 RangeEnumerator。其中用 yield return 语句来递增值。该结果也可以与其他扩展方法一起用。
? 1 2 3 4 5 6 7 var values Enumerable.Range(1, 5).Select(n gt; n * 3); foreach (var value in values) { Console.WriteLine(value); } // 3 6 9 12 15 3) Repeat
生成包含一个重复值的序列 IEnumerable。 Repeat() 方法 返回一个迭代器把同一个值重复特定的次数。
? 1 2 3 4 5 6 7 8 9 IEnumerablelt;stringgt; strings Enumerable.Repeat(I like programming., 3); foreach (String str in strings) { Console.WriteLine(str); } //I like programming. //I like programming. //I like programming. 十二、量词操作符
如果元素序列满足指定的条件量词操作符就返回布尔值。 1) Any
确定序列是否包含任何元素或确定序列中的任何元素是否都满足条件。
? 1 2 3 4 //获取是否存在姓为“Schumacher”的车手冠军 var hasRacer_Schumacher Formula1.GetChampions().Any(r gt; r.LastName Schumacher); Console.WriteLine(hasRacer_Schumacher); //True 2) All
确定序列中的所有元素是否满足条件。 3) Contains
确定序列是否包含指定的元素。 十三、元素操作符
这些元素操作符仅返回一个元素不是IEnumerable。默认值值类型默认为0引用类型默认为null
业务说明获取冠军数排名第三的车手冠军
? 1 2 3 4 5 6 var Racer3 Formula1.GetChampions() .OrderByDescending(r gt; r.Wins) .ElementAtOrDefault(2); Console.WriteLine(Racer3); //Ayrton Senna
1) First返回序列中的第一个元素如果是空序列此方法将引发异常。2) FirstOrDefault返回序列中的第一个元素如果是空序列则返回默认值default(TSource)。3) Last返回序列的最后一个元素如果是空序列此方法将引发异常。4) LastOrDefault返回序列中的最后一个元素如果是空序列则返回默认值default(TSource)。5) Single返回序列的唯一元素如果是空序列或序列包含多个元素此方法将引发异常。6) SingleOrDefault返回序列中的唯一元素如果是空序列则返回默认值default(TSource)如果该序列包含多个元素此方法将引发异常。7) ElementAt返回序列中指定索引处的元素索引从0开始如果索引超出范围此方法将引发异常。8) ElementAtOrDefault返回序列中指定索引处的元素索引从0开始如果索引超出范围则返回默认值default(TSource)。 十四、并行查询并行Linq
AsParallel() 方法扩展 IEnumerable 接口返回 ParallelQuery类所以正常的集合类可以以平行方式查询。
? 1 var query24 from r in Formual.GetChampions().AsParallel() select r; 十五、分区器
AsParallel()方法不仅扩展了 IEnumerable 接口还扩展了 Partitioner 类。通过它可以影响创建的分区。
手动创建一个分区器
? 1 var query25 from r in Partitioner.Create (Formual.GetChampions(), true).AsParallel() select r; 十六、取消
.NET 提供一个标准方法来取消长时间运行的任务也适用于并行Linq。
要取消长时间运行的查询可以给查询添加WithCancellation() 方法并传递一个 CancellactionToken令牌作为参数。
CancelllationToken令牌从CancellactionTokenSource类中创建。该查询在单独的线程中运行在该线程中捕获一个OperationCanceledException类型的异常。如果取消了查询就触发这个异常。
在主线程中调用CancellationTokenSource类的Cancel()方法可以取消任务。
? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 CancellationTokenSource cts new CancellationTokenSource(); Task.Factory.StartNew(() gt; { try { var res from r in Formual.GetChampions().AsParallel().WithCancellation(cts.Token) select r; Console.WriteLine(query finished, sum:{0}, res); } catch (OperationCanceledException ex) { Console.WriteLine(canceled!); Console.WriteLine(ex.Message); } }); string input Console.ReadLine(); if (input.ToLower().Equals(y)) { cts.Cancel(); Console.WriteLine(canceled 2!);