class Program
{
//linq基本子句
static void Main(string[] args)
{
//数组的基类是Array,而Array则实现了IEnumerable接口及GetEnumerator方法,因此数组可以使用LINQ进行查询,当然其本身也支持foreach
int[] array = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
List<int> list = new List<int>();
//LINQ返回一个IEnumerable集合,从而支持foreach遍历
//LINQ基本格式 var<变量>=from <项目>in<数据源> where <条件表达式> orderby<表达式>select<项目>,注意select选取的是筛选后的结果集
//1.from <项目> in <数据源> ...select <项目>,解释为从数据源中获取项目,from可以嵌套from,from的使用必须要求支持IEnumerable及其泛型版本的类型,from子句是必须的
//2.select子句也是必须的
//3.where子句可以复用,复用可以使用&&或者where,表示即...又...,where <项目>.contains(<字符串>),表示查询匹配<字符串>的内容
//4.orderby对数据进行排序,descending降序
//5.group分组,分组要求<项目>本身支持分组,分组会返回IGrouping<TK,TV>的序列,因此在输出需要的值时就需要双重foreach循环,外层foreach(var element in result)内层foreach( class p in element)
//6.into子句,用于创建临时标识对象,需要以select/group作为结尾子句否则异常
var result = from element in array where element > 5 select element;
foreach(var i in result)
{
Console.WriteLine(i);
}
Console.ReadLine();
}
}
要注意Linq的查询语句属于延迟加载,延迟加载示例如下:
static void Main(string[] args)
{
//数组的基类是Array,而Array则实现了IEnumerable接口及GetEnumerator方法,因此数组可以使用LINQ进行查询,当然其本身也支持foreach
int[] array = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 };
List<int> list = new List<int>();
//LINQ返回一个IEnumerable集合,从而支持foreach遍历
//LINQ基本格式 var<变量>=from <项目>in<数据源> where <条件表达式> orderby<表达式>select<项目>,注意select选取的是筛选后的结果集
//1.from <项目> in <数据源> ...select <项目>,解释为从数据源中获取项目,from可以嵌套from,from的使用必须要求支持IEnumerable及其泛型版本的类型,from子句是必须的
//2.select子句也是必须的
//3.where子句可以复用,复用可以使用&&或者where,表示即...又...,where <项目>.contains(<字符串>),表示查询匹配<字符串>的内容
//4.orderby对数据进行排序,descending降序
//5.group分组,分组要求<项目>本身支持分组,分组会返回IGrouping<TK,TV>的序列,因此在输出需要的值时就需要双重foreach循环,外层foreach(var element in result)内层foreach( class p in element)
//6.into子句,用于创建临时标识对象,需要以select/group作为结尾子句否则异常
var result = from element in array where element > 5 select element;
foreach(var i in result)
{
Console.WriteLine(i);
}
//验证延迟加载
Console.WriteLine("以下是验证延迟加载");
array[0] = 99;
//默认情况下linq自带延迟加载,按照一般的执行原理,修改数组元素不会影响result的遍历输出,也就是若不存在延迟加载原理的话,前后遍历输出应当一致
//事实上,前后输出不同,下面的foreach输出了修改后的数组,证明了延迟加载的存在
//linq延迟加载表示linq语句不会在声明的时候执行,而是在真正使用时才会具体调用执行,这里就是foreach时才会具体去执行linq
foreach(var i in result)
{
Console.WriteLine(i);
//output 99,2,3,4,5,6,7,8,9,10,11
}
Console.ReadLine();
}
默认情况下linq模式就是延迟执行,在获取对象本身时并不会获取关联的其他对象而是在访问时才会加载关联对象数据到内存,好处是不会出现在第一次访问时就加载大量数据造成系统和网络高负荷。但例如上面的两次foreach就会执行两次延迟加载,类似这样的多次查询反而会因为延迟加载加大开销。
解决办法:
简单的环境需求下,使用var list=result.ToList<对应类型>()/ToArray等;可以将查询结果缓存到list变量中,从而避免延迟执行的效率问题,但大量数据的加载本身也是高开销。
以linq to sql为例,msdn的解决办法包括使用DataLoadOptions的LoadWith方法来指定应当同时检索那些与主数据关联的数据;AssociateWith方法则可以限制检索数据量。因涉及DataContext暂不细说,留待EF下细说。