LINQ Query Keywords
[索引页]
谢谢来访!上一次我们谈到LINQ to DataSet
这一次我们谈的是C#查询keywords,就是大家熟悉的在LINQ中的from,group,select,into,where.可能会大家感觉有点长, 但是比较基础的,你懂的可以一扫而过!
还有提供LINQ的三工具的下载!就大家知道的linqpad,QueryVisualizer插件,VLinq可视化编辑器.!
请多指正!
C# 查询keywords
我知道的关于LINQ的工具
linqpad: http://www.linqpad.net/
QueryVisualizer:http://www.scottgu.com/blogposts/linqquery/
SqlServerQueryVisualizer.zip
VLinq:http://code.msdn.microsoft.com/vlinq
from:一个查询表达式的开始,如果有子查询也由它开始,指向数据源.有一个本地范围变量(range variable)来表示来源数据.他们都是强类型的.而这里的from引用的数据源必须有一个IEnumerable, IEnumerable(T)类型,或IQueryable(T).
这里提到的范围变量,就是编译器可以在当数据源实现IEnumerable(T)类型时推断这个范围变量的类型,如果源数据已有类型为IEnumerable(T),之后这个范围变量就在会被使用时推断变量类型.这里如果你的源数据没有指定泛性的IEnumerable类型,那你只有明确的指定变量类型.
下面是使用LINQ查寻ArrayList,
数据源
在上面就使用非泛性的IEnumerable类型的集合ArrayList,你必须明确的指定类型,在这里from Student student,就指定类型!明确指定范围变量(range variable)就同调用Cast(TResult)方法一样的效果.Cast(TResult)和OfType(TResult)都操作非泛性IEnumberable类型的标准操作符.
以前我们谈过关于IEnumerable(T),所以只看泛性形式是怎样写的(就是大家熟悉的这个事例)
接下来我们再看是Cast(TResult)方法
它转换IEnumerable类型的元素为指定类型.他的返回类型为IEnumerable(T).其实这个方法要被延迟执行的,就是延迟到foreach使用它时候才被执行,没有被激活时返回Object里面放有所有在被激活时所有需要的所有信息.Cast(TResult)方法可以让一些不能实现IEnumerable(T)类型的类进行转换,如果ArrayList!看下面实现:
而因为Cast(TResult)只能简单转化类型的但是如果在它集合里面有不转换的它就会抛出一个异常,只不过这里我们可以使用OfType(TResult)方法来过滤不被传换的,而不用抛出一个异常!
OfType(TResult)方法
基于指定类型的来过滤IEnumerable的元素.返回一个IEnumerable(T).它也同样要被延迟的.这个方法适合应用在非参数化类型的集合中,如ArrayList,因为OfType(TResult)方法扩展类型为IEnumerable.OfType(TResult)不能应用于参数化集合中IEnumerable(T).
上面是过滤了不能转换成指定类的项,第二个查寻是将arraylist中包括得有字符'n'每一项输出.
接下来是多个from的内连查询
二Where,select
(1)Where:这个与SQL基本没什么不同,起一个过滤作用,能使用在group之前或之后.
(2)select:而select也基本一样,这里select是指定range variable详细信息,还有一个作用就是指定query variable(这个就在LINQ中的一般查寻的结构能看懂吧:var query variable = from string range variable in myName select range variable).
三group
Group返回的是一个IGrouping(TKey, TElement)的有序对象包括0个或更多个匹配分组的键值的项.
我们需要先知道IGrouping(TKey, TElement);
参数:
TKey:是在IGrouping(TKey, TElement)中key的类型,
TElement:在IGrouping(TKey, TElement)中值的类型
IGrouping(TKey, TElement)是一个IEnumerable(T)多加一个Key,而这个key在这个里面是属性,也是这个里面每一个值都有的共同的这个属性,这个key我们可以指定实体中任何存在的值.当然也可以是任何类型.下面的事例来于MSDN中的,就反射String对象中的成员,我们再将这些成员按Key分组输出.(你可以把 First()方法换成Last方法来调试,你就知道Group关键是指定这个Key).
因为IGrouping(TKey, TElement)对象由group产生,实质就是一个List,所以你必须使用foreach.而且在执行时是keySelector和ElementSelector同时存在。
这里运行时的IL
elementSelector =
{System.Func<CSharpLanguage_C_app.LinqAPP.Linqkey.keyWord2.Student,
CSharpLanguage_C_app.LinqAPP.Linqkey.keyWord2.Student>}
base {System.Delegate} = {System.Func<CSharpLanguage_C_app.LinqAPP.Linqkey.keyWord2.Student,
CSharpLanguage_C_app.LinqAPP.Linqkey.keyWord2.Student>}
keySelector = {System.Func<CSharpLanguage_C_app.LinqAPP.Linqkey.keyWord2.Student,char>}
base {System.MulticastDelegate} = {System.Func<CSharpLanguage_C_app.LinqAPP.Linqkey.keyWord2.Student,char>}
base {System.Delegate} = {System.Func<CSharpLanguage_C_app.LinqAPP.Linqkey.keyWord2.Student,char>}
回到我们的Group中来看代码,
数据源:
一般的使用
key可以是任何值
还可以使用匿名类创建混合的KEY.
IGrouping<key,Element>得用法
Into
Into就是创建一个暂时标识来保存经过selelct, group,join等处理过的数据.
orderby
orderby用来排序,指定一个key,按照这个key来排序,指定多个Key,就能出现多级别排序!在标准的查操作符,有
OrderBy,ThenBy 升序
OrderByDescending,ThenByDescending 降序
Reverse 反转
返回类型 IOrderedEnumerable<TSource>
这里我们要来谈谈IOrderedEnumerable(TElement)接口
它表示一个排序,OrderBy,ThenBy 都是扩展它。
public interface IOrderedEnumerable<TElement> : IEnumerable<TElement>,
IEnumerable
一个IOrderedEnumerable(TElement)的对象能通过调用第一级OrderBy或OrderByDescending排序方法获得,而输入的参数是IEnumerable<TSource>,返回一个IOrderedEnumerable(TElement). ThenBy and ThenByDescending,是子级排序方法,输入的参数类型IOrderedEnumerable(TElement)为还是返回的IOrderedEnumerable(TElement).
Join以后会单独谈,let在之前已经谈到!
worksguo
谢谢来访!上一次我们谈到LINQ to DataSet
这一次我们谈的是C#查询keywords,就是大家熟悉的在LINQ中的from,group,select,into,where.可能会大家感觉有点长, 但是比较基础的,你懂的可以一扫而过!
还有提供LINQ的三工具的下载!就大家知道的linqpad,QueryVisualizer插件,VLinq可视化编辑器.!
请多指正!
C# 查询keywords
我知道的关于LINQ的工具
linqpad: http://www.linqpad.net/
QueryVisualizer:http://www.scottgu.com/blogposts/linqquery/
SqlServerQueryVisualizer.zip
VLinq:http://code.msdn.microsoft.com/vlinq
From
from:一个查询表达式的开始,如果有子查询也由它开始,指向数据源.有一个本地范围变量(range variable)来表示来源数据.他们都是强类型的.而这里的from引用的数据源必须有一个IEnumerable, IEnumerable(T)类型,或IQueryable(T).
这里提到的范围变量,就是编译器可以在当数据源实现IEnumerable(T)类型时推断这个范围变量的类型,如果源数据已有类型为IEnumerable(T),之后这个范围变量就在会被使用时推断变量类型.这里如果你的源数据没有指定泛性的IEnumerable类型,那你只有明确的指定变量类型.
下面是使用LINQ查寻ArrayList,
数据源
Code
//Use an explicit type for non-generic collections,and query it
var query = from Student student in arrList
where student.Scores[0] > 90 select student;
foreach (Student s in query)
{
Console.WriteLine(s.LastName + ":" + s.Scores[0]);
}
Console.ReadLine();
var query = from Student student in arrList
where student.Scores[0] > 90 select student;
foreach (Student s in query)
{
Console.WriteLine(s.LastName + ":" + s.Scores[0]);
}
Console.ReadLine();
在上面就使用非泛性的IEnumerable类型的集合ArrayList,你必须明确的指定类型,在这里from Student student,就指定类型!明确指定范围变量(range variable)就同调用Cast(TResult)方法一样的效果.Cast(TResult)和OfType(TResult)都操作非泛性IEnumberable类型的标准操作符.
以前我们谈过关于IEnumerable(T),所以只看泛性形式是怎样写的(就是大家熟悉的这个事例)
class LINQQueryExpressions
{
static void Main()
{
// Specify the data source.
int[] scores = new int[] { 97, 92, 81, 60 };
// Define the query expression.
IEnumerable<int> scoreQuery =
from score in scores
where score > 80
select score;
// Execute the query.
foreach (int i in scoreQuery)
{
Console.Write(i + " ");
}
}
}
{
static void Main()
{
// Specify the data source.
int[] scores = new int[] { 97, 92, 81, 60 };
// Define the query expression.
IEnumerable<int> scoreQuery =
from score in scores
where score > 80
select score;
// Execute the query.
foreach (int i in scoreQuery)
{
Console.Write(i + " ");
}
}
}
接下来我们再看是Cast(TResult)方法
它转换IEnumerable类型的元素为指定类型.他的返回类型为IEnumerable(T).其实这个方法要被延迟执行的,就是延迟到foreach使用它时候才被执行,没有被激活时返回Object里面放有所有在被激活时所有需要的所有信息.Cast(TResult)方法可以让一些不能实现IEnumerable(T)类型的类进行转换,如果ArrayList!看下面实现:
Console.WriteLine("use generic IEnumerable collections");
IEnumerable<Student> query2 =
arrList.Cast<Student>().Select(arrLists => arrLists);
foreach (Student s in query2)
{
Console.WriteLine(s.LastName + ":" + s.Scores[0]);
}
Console.ReadLine();
比较简单!IEnumerable<Student> query2 =
arrList.Cast<Student>().Select(arrLists => arrLists);
foreach (Student s in query2)
{
Console.WriteLine(s.LastName + ":" + s.Scores[0]);
}
Console.ReadLine();
而因为Cast(TResult)只能简单转化类型的但是如果在它集合里面有不转换的它就会抛出一个异常,只不过这里我们可以使用OfType(TResult)方法来过滤不被传换的,而不用抛出一个异常!
//use Cast<T>() method
Console.WriteLine("use Cast<T>() method");
ArrayList fruits = new ArrayList();
fruits.Add("apple");
fruits.Add("mango");
IEnumerable<string> query3 =
fruits.Cast<string>().Select(fruit => fruit);
foreach (string fruit in query3)
{
Console.WriteLine(fruit);
}
Console.ReadLine();
Console.WriteLine("use Cast<T>() method");
ArrayList fruits = new ArrayList();
fruits.Add("apple");
fruits.Add("mango");
IEnumerable<string> query3 =
fruits.Cast<string>().Select(fruit => fruit);
foreach (string fruit in query3)
{
Console.WriteLine(fruit);
}
Console.ReadLine();
OfType(TResult)方法
基于指定类型的来过滤IEnumerable的元素.返回一个IEnumerable(T).它也同样要被延迟的.这个方法适合应用在非参数化类型的集合中,如ArrayList,因为OfType(TResult)方法扩展类型为IEnumerable.OfType(TResult)不能应用于参数化集合中IEnumerable(T).
//OfType<T>() method
Console.WriteLine("OfType<T>() method");
ArrayList fruits2 = new ArrayList(4);
fruits2.Add("Mango");
fruits2.Add("Orang2");
fruits2.Add("Apple2");
fruits2.Add(3.0);
fruits2.Add("Banana2");
IEnumerable<string> query4 = fruits2.OfType<string>();
Console.WriteLine("Elements of type 'string' are:");
foreach (string fruit in query4)
{
Console.WriteLine(fruit);
}
IEnumerable<string> query5 =
fruits2.OfType<string>().Where(fruit => fruit.ToLower().Contains("n"));
Console.WriteLine("\nThe following strings contain 'n':");
foreach (string fruit in query5)
{
Console.WriteLine(fruit);
}
Console.ReadLine();
Console.WriteLine("OfType<T>() method");
ArrayList fruits2 = new ArrayList(4);
fruits2.Add("Mango");
fruits2.Add("Orang2");
fruits2.Add("Apple2");
fruits2.Add(3.0);
fruits2.Add("Banana2");
IEnumerable<string> query4 = fruits2.OfType<string>();
Console.WriteLine("Elements of type 'string' are:");
foreach (string fruit in query4)
{
Console.WriteLine(fruit);
}
IEnumerable<string> query5 =
fruits2.OfType<string>().Where(fruit => fruit.ToLower().Contains("n"));
Console.WriteLine("\nThe following strings contain 'n':");
foreach (string fruit in query5)
{
Console.WriteLine(fruit);
}
Console.ReadLine();
上面是过滤了不能转换成指定类的项,第二个查寻是将arraylist中包括得有字符'n'每一项输出.
接下来是多个from的内连查询
ArrayList fruits1 = new ArrayList(2);
fruits1.Add("apple");
fruits1.Add("Mango");
var query7 = from string fur in fruits1
where fur!="apple"
from string fur2 in fruits2
where fur2 != "Mango"
select new { fur, fur2 };
foreach(var AllFruits in query7)
{
Console.WriteLine("fur equal to mango:" +AllFruits.fur);
Console.WriteLine("fur2 non equal to mango:" + AllFruits.fur2);
}
Console.ReadKey();
fruits1.Add("apple");
fruits1.Add("Mango");
var query7 = from string fur in fruits1
where fur!="apple"
from string fur2 in fruits2
where fur2 != "Mango"
select new { fur, fur2 };
foreach(var AllFruits in query7)
{
Console.WriteLine("fur equal to mango:" +AllFruits.fur);
Console.WriteLine("fur2 non equal to mango:" + AllFruits.fur2);
}
Console.ReadKey();
二Where,select
(1)Where:这个与SQL基本没什么不同,起一个过滤作用,能使用在group之前或之后.
(2)select:而select也基本一样,这里select是指定range variable详细信息,还有一个作用就是指定query variable(这个就在LINQ中的一般查寻的结构能看懂吧:var query variable = from string range variable in myName select range variable).
三group
Group返回的是一个IGrouping(TKey, TElement)的有序对象包括0个或更多个匹配分组的键值的项.
我们需要先知道IGrouping(TKey, TElement);
public interface IGrouping <TKey,TElement> : IEnumerable<TElement>,
IEnumerable
{
TKey Key { get; } // Key applies to the subsequence as a whole
}
IEnumerable
{
TKey Key { get; } // Key applies to the subsequence as a whole
}
参数:
TKey:是在IGrouping(TKey, TElement)中key的类型,
TElement:在IGrouping(TKey, TElement)中值的类型
IGrouping(TKey, TElement)是一个IEnumerable(T)多加一个Key,而这个key在这个里面是属性,也是这个里面每一个值都有的共同的这个属性,这个key我们可以指定实体中任何存在的值.当然也可以是任何类型.下面的事例来于MSDN中的,就反射String对象中的成员,我们再将这些成员按Key分组输出.(你可以把 First()方法换成Last方法来调试,你就知道Group关键是指定这个Key).
//use IGroup
IGrouping<MemberTypes, MemberInfo> group =
typeof(String).GetMembers().GroupBy(member => member.MemberType).First();
Console.WriteLine("\nValues that have the key'{0}':", group.Key);
foreach (MemberInfo mi in group)
Console.WriteLine(mi.Name);
Console.ReadKey();
IGrouping<MemberTypes, MemberInfo> group =
typeof(String).GetMembers().GroupBy(member => member.MemberType).First();
Console.WriteLine("\nValues that have the key'{0}':", group.Key);
foreach (MemberInfo mi in group)
Console.WriteLine(mi.Name);
Console.ReadKey();
因为IGrouping(TKey, TElement)对象由group产生,实质就是一个List,所以你必须使用foreach.而且在执行时是keySelector和ElementSelector同时存在。
这里运行时的IL
elementSelector =
{System.Func<CSharpLanguage_C_app.LinqAPP.Linqkey.keyWord2.Student,
CSharpLanguage_C_app.LinqAPP.Linqkey.keyWord2.Student>}
base {System.Delegate} = {System.Func<CSharpLanguage_C_app.LinqAPP.Linqkey.keyWord2.Student,
CSharpLanguage_C_app.LinqAPP.Linqkey.keyWord2.Student>}
keySelector = {System.Func<CSharpLanguage_C_app.LinqAPP.Linqkey.keyWord2.Student,char>}
base {System.MulticastDelegate} = {System.Func<CSharpLanguage_C_app.LinqAPP.Linqkey.keyWord2.Student,char>}
base {System.Delegate} = {System.Func<CSharpLanguage_C_app.LinqAPP.Linqkey.keyWord2.Student,char>}
回到我们的Group中来看代码,
数据源:
Code
一般的使用
List<Student> students = GetStudents();
var booleanGroupQuery = from student in students
group student by student.Scores.Average() >= 80;
foreach (var studentGroup in booleanGroupQuery)
{
Console.WriteLine(studentGroup.Key
== true ? "High averages" : "Low averages");
foreach (var student in studentGroup)
{
Console.WriteLine(" {0}, {1}:{2}",
student.Last, student.First, student.Scores.Average());
}
}
var booleanGroupQuery = from student in students
group student by student.Scores.Average() >= 80;
foreach (var studentGroup in booleanGroupQuery)
{
Console.WriteLine(studentGroup.Key
== true ? "High averages" : "Low averages");
foreach (var student in studentGroup)
{
Console.WriteLine(" {0}, {1}:{2}",
student.Last, student.First, student.Scores.Average());
}
}
key可以是任何值
var studentQuery2 = from student in students
let avg = (int)student.Scores.Average()
group student by (avg == 0 ? 0 : avg / 100) into g
orderby g.Key
select g;
foreach (var studentGroup2 in studentQuery2)
{
int temp = studentGroup2.Key * 10;
Console.WriteLine("Students with an average between {0} and {1}",
temp, temp + 10);
foreach (var student in studentGroup2)
{
Console.WriteLine(" {0}, {1}:{2}",
student.Last, student.First, student.Scores.Average());
}
}
let avg = (int)student.Scores.Average()
group student by (avg == 0 ? 0 : avg / 100) into g
orderby g.Key
select g;
foreach (var studentGroup2 in studentQuery2)
{
int temp = studentGroup2.Key * 10;
Console.WriteLine("Students with an average between {0} and {1}",
temp, temp + 10);
foreach (var student in studentGroup2)
{
Console.WriteLine(" {0}, {1}:{2}",
student.Last, student.First, student.Scores.Average());
}
}
还可以使用匿名类创建混合的KEY.
// Composite Keys
var studentQuery6 = from f in students
group f by new { FirstName = f.First[0], idNumeber = f.Last[0] };
foreach (var s in studentQuery6)
{
Console.WriteLine(s.Key);
foreach (var news in s)
{
Console.WriteLine(news.First + "___" + news.ID + "___" + news.Last);
}
}
var studentQuery6 = from f in students
group f by new { FirstName = f.First[0], idNumeber = f.Last[0] };
foreach (var s in studentQuery6)
{
Console.WriteLine(s.Key);
foreach (var news in s)
{
Console.WriteLine(news.First + "___" + news.ID + "___" + news.Last);
}
}
IGrouping<key,Element>得用法
//usage IGrouping<key,Element>
IEnumerable<IGrouping<char, Student>> studentQuery4 =
from student in students
group student by student.Last[0];
foreach (IGrouping<char, Student> group in studentQuery4)
{
Console.WriteLine(group.Key);
foreach (Student s in group)
{
Console.WriteLine(" {0}, {1}", s.Last, s.First);
}
}
IEnumerable<IGrouping<char, Student>> studentQuery4 =
from student in students
group student by student.Last[0];
foreach (IGrouping<char, Student> group in studentQuery4)
{
Console.WriteLine(group.Key);
foreach (Student s in group)
{
Console.WriteLine(" {0}, {1}", s.Last, s.First);
}
}
Into
Into就是创建一个暂时标识来保存经过selelct, group,join等处理过的数据.
ArrayList fruits2 = new ArrayList(4);
fruits2.Add("Mango");
fruits2.Add("Orang2");
fruits2.Add("Apple2");
fruits2.Add(3.0);
fruits2.Add("Banana2");
ArrayList fruits1 = new ArrayList(2);
fruits1.Add("apple");
fruits1.Add("Mango");
//keyWord into
var wordGroup1 = from string f in fruits2
group f by f[0] into fruitsGroup
where fruitsGroup.Count()>=1
select new {FirstLetter = fruitsGroup.Key,
Words = fruitsGroup.Count()};
foreach (var item in wordGroup1)
{
Console.WriteLine("{0} has {1} element.", item.FirstLetter, item.Words);
}
Console.WriteLine("Press any key to exit.");
Console.ReadKey();
var fruitsCount = from string f in fruits1 group f by f[3]
into fruitsGroups
select fruitsGroups.Key;
foreach (var item in fruitsCount)
{
Console.WriteLine(item);
}
Console.WriteLine("Press any key to exit.");
Console.ReadKey();
fruits2.Add("Mango");
fruits2.Add("Orang2");
fruits2.Add("Apple2");
fruits2.Add(3.0);
fruits2.Add("Banana2");
ArrayList fruits1 = new ArrayList(2);
fruits1.Add("apple");
fruits1.Add("Mango");
//keyWord into
var wordGroup1 = from string f in fruits2
group f by f[0] into fruitsGroup
where fruitsGroup.Count()>=1
select new {FirstLetter = fruitsGroup.Key,
Words = fruitsGroup.Count()};
foreach (var item in wordGroup1)
{
Console.WriteLine("{0} has {1} element.", item.FirstLetter, item.Words);
}
Console.WriteLine("Press any key to exit.");
Console.ReadKey();
var fruitsCount = from string f in fruits1 group f by f[3]
into fruitsGroups
select fruitsGroups.Key;
foreach (var item in fruitsCount)
{
Console.WriteLine(item);
}
Console.WriteLine("Press any key to exit.");
Console.ReadKey();
orderby
orderby用来排序,指定一个key,按照这个key来排序,指定多个Key,就能出现多级别排序!在标准的查操作符,有
OrderBy,ThenBy 升序
OrderByDescending,ThenByDescending 降序
Reverse 反转
返回类型 IOrderedEnumerable<TSource>
这里我们要来谈谈IOrderedEnumerable(TElement)接口
它表示一个排序,OrderBy,ThenBy 都是扩展它。
public interface IOrderedEnumerable<TElement> : IEnumerable<TElement>,
IEnumerable
一个IOrderedEnumerable(TElement)的对象能通过调用第一级OrderBy或OrderByDescending排序方法获得,而输入的参数是IEnumerable<TSource>,返回一个IOrderedEnumerable(TElement). ThenBy and ThenByDescending,是子级排序方法,输入的参数类型IOrderedEnumerable(TElement)为还是返回的IOrderedEnumerable(TElement).
IEnumerable<string> sortAscendingQuery = from string f in fruits2 orderby f
select f;
foreach(string s in sortAscendingQuery)
{
Console.WriteLine(s);
}
IEnumerable<string> sortDescendingQuery = from string f in fruits2
orderby f descending select f;
foreach (string s in sortDescendingQuery)
{
Console.WriteLine(s);
}
Console.WriteLine("Press any key to exit.");
Console.ReadKey();
select f;
foreach(string s in sortAscendingQuery)
{
Console.WriteLine(s);
}
IEnumerable<string> sortDescendingQuery = from string f in fruits2
orderby f descending select f;
foreach (string s in sortDescendingQuery)
{
Console.WriteLine(s);
}
Console.WriteLine("Press any key to exit.");
Console.ReadKey();
Join以后会单独谈,let在之前已经谈到!
worksguo