微软刚推出LINQ的时候自己对其前途及作用很是表示怀疑,尤其是其性能表现更是不敢相信,以致很长时间内没有深入接触就把它扔到一边去了。最近一阵时间由于工作关系需要深入理解并应用LINQ技术,且需要结合EF框架使用。经过一阵时间的学习,发现LINQ决对值得你去了解并使用,LINQ非常易用而且可靠。微软之外的众多开发者已经纷纷开始 为其创造大量的第三方插件,这样足以保证它在相当长时间内具有顽强的生命力。总结下来其具有如下优点:
- 简单易用,新手只需要简单学习就可以完全掌握其基本应用,大大提高了新开发者的开发效率。
- 以前要一大段代码才能完成的工作现在只要很少代码就可以完成相关工作,代码看去简洁而优雅
- 编译器可以自动检查LINQ语法的正确性,这可以让用户开发出更少错误的代码。
- 透明支持多数据源,你可以在几乎透明的情况下横跨多个不同数据源进行操作。
查询是一种从数据源检索数据的表达式。 查询通常用专门的查询语言来表示。 随着时间的推移,人们已经为各种数据源开发了不同的语言;例如,用于关系数据库的 SQL 和用于 XML 的 XQuery。 因此,开发人员不得不针对他们必须支持的每种数据源或数据格式而学习新的查询语言。 LINQ 通过提供一种跨各种数据源和数据格式使用数据的一致模型,简化了这一情况。 在 LINQ 查询中,始终会用到对象。 可以使用相同的基本编码模式来查询和转换 XML 文档、SQL 数据库、ADO.NET 数据集、.NET 集合中的数据以及对其有 LINQ 提供程序可用的任何其他格式的数据。 所有 LINQ 查询操作都由以下三个不同的操作组成: 获取数据源、创建查询、 执行查询。
// 1. 确定要查询的数据源
var numbers = new [] { 0 , 1 , 2 , 3 , 4 , 5 , 6 };
// 2. 创建查询表达式表达式返回的numQuery是一个IEnumerable<int>类型的对象
var numQuery =
from num in numbers
where (num % 2 ) == 0
select num;
// 3. 执行查询
foreach ( int num in numQuery)
{
Console.Write( " {0,1} " , num);
}
string sentence = "the quick brown fox jumps over the lazy dog";
string[] words = sentence.Split(' ');
var query = from word in words
group word.ToUpper() by word.Length into gr
orderby gr.Key
select new { Length = gr.Key, Words = gr };
var query2 = words.
GroupBy(w => w.Length, w => w.ToUpper()).
Select(g => new { Length = g.Key, Words = g }).
OrderBy(o => o.Length);
foreach (var obj in query)
{
Console.WriteLine("Words of length {0}:", obj.Length);
foreach (string word in obj.Words)
Console.WriteLine(word);
}
在 LINQ 中,查询的执行与查询本身截然不同;换句话说,如果只是创建查询变量,则不会检索任何数据。由于查询变量本身从不保存查询结果,因此可以根据需要随意执行查询。 例如,可以通过一个单独的应用程序持续更新数据库。 在应用程序中,可以创建一个检索最新数据的查询,并可以按某一时间间隔反复执行该查询以便每次检索不同的结果。 如果有需要可以通过调用一些聚合方法强制查询立即执行,此外,还可以通过在紧跟查询表达式之后的位置放置一个 foreach 循环来强制执行查询。 通过调用 ToList 或 ToArray,也可以将所有数据缓存在单个集合对象中。
下面语句是LINQ的另一种写法(基于方法的查询),其效果与上文的查询语句相同.
IEnumerable < int > numQuery2 = numbers.Where(num => num % 2 == 0 ).OrderBy(n => n);
var count = numQuery2.Count();
Console.WriteLine( " \n{0,1}个记录符合条件。 " , count);
若要了解基于方法的查询,让我们进一步地分析它。 注意,在表达式的右侧,where 子句现在表示为对 numbers 对象的实例方法,在您调用该对象时其返回类型为 IEnumerable<int>。 如果您熟悉泛型 IEnumerable<T> 接口,那么您就会了解,它不具有 Where 方法。 但是,在 Visual Studio IDE 中调用 IntelliSense 完成列表时将可以看到 Where 、Select、SelectMany、Join 和 Orderby等方法。
在上面的示例中,条件表达式 (num % 2 == 0) 是作为内联参数传递到 Where 方法的:Where(num => num % 2 == 0) 。此内联表达式称为 lambda 表达式。 将代码编写为匿名方法或泛型委托或表达式树是一种便捷的方法,否则编写起来就要麻烦得多。 在 C# 中,=> 是 lambda 运算符,可读为“goes to”。 运算符左侧的 num 是输入变量,与查询表达式中的 num 相对应。 编译器可推断 num 的类型,因为它了解 numbers 是泛型 IEnumerable<T> 类型。lambda 表达式与查询语法中的表达式或任何其他 C# 表达式或语句中的表达式相同;它可以包括方法调用和其他复杂逻辑。 “返回值”就是表达式结果。若要开始使用 LINQ,您不必大量使用 lambda。 但是,特定查询只可使用方法语法表示,其中一些查询需要使用 lambda 表达式。
基于LINQ查询一个自定义对象集合,如下面代码所示:
new User{Age = 11 ,UserEmail = " a@ss.com " ,UserName = " a " },
new User{Age = 21 ,UserEmail = " b@ss.com " ,UserName = " b " },
new User{Age = 21 ,UserEmail = " c@ss.com " ,UserName = " c " },
new User{Age = 32 ,UserEmail = " d@ss.com " ,UserName = " d " },
new User{Age = 33 ,UserEmail = " e@ss.com " ,UserName = " e " },
new User{Age = 15 ,UserEmail = " f@ss.com " ,UserName = " f " }
};
// 编写查询表达式
var userQueryResult = users.Where(a => a.Age > 10 && a.Age < 30 ).OrderByDescending(a => a.UserName) ;
// 输出结果
foreach (var user in userQueryResult)
{
Console.WriteLine(user.UserName);
}
// 更改数据源内容
users = new List < User > ()
{
new User{Age = 11 ,UserEmail = " a1@ss.com " ,UserName = " a1 " },
new User{Age = 21 ,UserEmail = " b1@ss.com " ,UserName = " b1 " },
new User{Age = 21 ,UserEmail = " c1@ss.com " ,UserName = " c1 " },
new User{Age = 32 ,UserEmail = " d1@ss.com " ,UserName = " d1 " },
new User{Age = 33 ,UserEmail = " e1@ss.com " ,UserName = " e1 " },
new User{Age = 15 ,UserEmail = " f1@ss.com " ,UserName = " 1f " }
};
// 更改数据源内容后,发现输出没有改变
foreach (var user in userQueryResult)
{
Console.WriteLine(user.UserName);
}
// 重新定义查询对象
userQueryResult = users.Where(a => a.Age > 10 && a.Age < 30 ).OrderByDescending(a => a.UserName);
foreach (var user in userQueryResult)
{
Console.WriteLine(user.UserName);
}