LINQ 技术(即 LINQ to Entities)使开发人员能够通过使用 LINQ 表达式和 LINQ 标准查询运算符,直接从开发环境中针对 实体框架对象上下文创建灵活的强类型查询。LINQ to Entities 查询使用对象服务基础结构。ObjectContext 类是作为 CLR 对象与 实体数据模型 进行交互的主要类。开发人员通过 ObjectContext 构造泛型 ObjectQuery 实例。ObjectQuery 泛型类表示一个查询,此查询返回一个由类型化实体组成的实例或集合。返回的实体对象可供更新并位于对象上下文中。以下是创建和执行 LINQ to Entities 查询的过程:
1. 从 ObjectContext 构造 ObjectQuery 实例。
2. 通过使用 ObjectQuery 实例在 C# 或 Visual Basic 中编写 LINQ to Entities 查询。
3. 将 LINQ 标准查询运算符和表达式将转换为命令目录树。
4. 对数据源执行命令目录树表示形式的查询。执行过程中在数据源上引发的任何异常都将直接向上传递到客户端。
5. 将查询结果返回到客户端。
Code 一、Linq To Entities简单查询 下面将介绍简单的Linq To Entities查询,相关的查询语法可以使用基于表达式或基于方法的语法。本节使用的TestDriver.Net配合Nunit2.4进行测试。 1 , 投影 代码如下: using System; using System.Collections.Generic; using System.Linq; using System.Data.Objects; using NUnit.Framework; namespace NorthWindModel { [TestFixture] public class TestEFModel { [Test] public void Select() { using (var edm = new NorthwindEntities()) { // 基于表达式的查询语法 ObjectQuery < Customers > customers = edm.Customers; IQueryable < Customers > cust1 = from c in customers select c; Assert.Greater(cust1.Count(), 0 ); // 使用ObjectQuery类的ToTraceString()方法显示查询SQL语句 Console.WriteLine(customers.ToTraceString()); } } } } 输出: SELECT [Extent1].[CustomerID] AS [CustomerID], [Extent1].[CompanyName] AS [CompanyName], [Extent1].[ContactName] AS [ContactName], [Extent1].[ContactTitle] AS [ContactTitle], [Extent1].[Address] AS [Address], [Extent1].[City] AS [City], [Extent1].[Region] AS [Region], [Extent1].[PostalCode] AS [PostalCode], [Extent1].[Country] AS [Country], [Extent1].[Phone] AS [Phone], [Extent1].[Fax] AS [Fax] FROM [dbo].[Customers] AS [Extent1] 1 passed, 0 failed, 0 skipped, took 11.00 seconds (NUnit 2.4 ). 在上面的输出内容中,可以看到使用了ToTraceString()方法来输出具体的SQL语句。同时Nunit也输出相关的测试情况,请注意查询所花费的时间,以便我们进行查询速度的分析比较。 2 , 条件限制 using (var edm = new NorthwindEntities()) { // 基于表达式的查询语法 ObjectQuery < Customers > customers = edm.Customers; IQueryable < Customers > cust1 = from c in customers where c.CustomerID == " ALFKI " select c; Assert.AreEqual(cust1.Count(), 1 ); foreach (var c in cust1) Console.WriteLine( " CustomerID={0} " , c.CustomerID); // 基于方法的查询语法 var cust2 = edm.Customers.Where(c => c.CustomerID == " ALFKI " ); Assert.AreEqual(cust2.Count(), 1 ); foreach (var c in cust2) Console.WriteLine( " CustomerID={0} " , c.CustomerID); } 3 , 排序和分页 在使用Skip和Take方法实现分页时,必须先对数据进行排序,否则将会抛异常。 using (var edm = new NorthwindEntities()) { // 基于表达式的查询语法 ObjectQuery < Customers > customers = edm.Customers; IQueryable < Customers > cust10 = (from c in customers orderby c.CustomerID select c).Skip( 0 ).Take( 10 ); Assert.AreEqual(cust10.Count(), 10 ); foreach (var c in cust10) Console.WriteLine( " CustomerID={0} " , c.CustomerID); // 基于方法的查询语法 var cust = edm.Customers.OrderBy(c => c.CustomerID).Skip( 0 ).Take( 10 ); Assert.AreEqual(cust.Count(), 10 ); foreach (var c in cust) Console.WriteLine( " CustomerID={0} " , c.CustomerID); } 4 , 聚合 可使用的聚合运算符有Average、Count、Max、Min 和 Sum。 using (var edm = new NorthwindEntities()) { var maxuprice = edm.Products.Max(p => p.UnitPrice); Console.WriteLine(maxuprice.Value); } 5 , 连接 可以的连接有Join 和 GroupJoin 方法。GroupJoin组联接等效于左外部联接,它返回第一个(左侧)数据源的每个元素(即使其他数据源中没有关联元素)。 using (var edm = new NorthwindEntities()) { var query = from d in edm.Order_Details join order in edm.Orders on d.OrderID equals order.OrderID select new { OrderId = order.OrderID, ProductId = d.ProductID, UnitPrice = d.UnitPrice }; foreach (var q in query) Console.WriteLine( " {0},{1},{2} " ,q.OrderId,q.ProductId,q.UnitPrice); } 其他一些方法等就不多说了,和Linq to SQL 基本上是一样的。 二、LINQ to Entities 查询注意事项 l 排序信息丢失 如果在排序操作之后执行了任何其他操作,则不能保证这些附加操作中会保留排序结果。这些操作包括 Select 和 Where 等。另外,采用表达式作为输入参数的 First 和 FirstOrDefault 方法不保留顺序。 如下代码:并不能达到反序排序的效果 using (var edm = new NorthwindEntities()) { IQueryable < Customers > cc = edm.Customers.OrderByDescending(c => c.CustomerID).Where(c => c.Region != null ).Select(c => c); foreach (var c in cc) Console.WriteLine(c.CustomerID); } l 不支持无符号整数 由于 实体框架不支持无符号整数,因此不支持在 LINQ to Entities 查询中指定无符号整数类型。如果指定无符号整数,则在查询表达式转换过程中会引发 NotSupportedException异常,并显示无法创建类型为“结束类型”的常量值。此上下文仅支持基元类型(“例如 Int32、String 和 Guid”)。 如下将会报异常的代码: using (var edm = new NorthwindEntities()) { uint id = UInt32.Parse( " 123 " ); IQueryable < string > produt = from p in edm.Products where p.UnitPrice == id select p.ProductName; foreach ( string name in produt) Console.WriteLine(name); } 上面的代码中,由于id是uint而不是Int32,String,Guid的标量类型,所以在执行到where p.UnitPrice == id这个地方时,会报异常。 l 不支持引用非标量闭包 不支持在查询中引用非标量闭包(如实体)。在执行这类查询时,会引发 NotSupportedException 异常,并显示消息“无法创建类型为“结束类型”的常量值。此上下文中仅支持基元类型(‘如 Int32、String 和 Guid’) 如下将会报异常的代码: using (var edm = new NorthwindEntities()) { Customers customer = edm.Customers.FirstOrDefault(); IQueryable < string > cc = from c in edm.Customers where c == customer select c.ContactName; foreach ( string name in cc) Console.WriteLine(name); } 上面的代码中,由于customer是引用类型而不是Int32,String,Guid的标量类型,所以在执行到where c == customer这个地方时,会报异常。 好.
版权说明
如果标题未标有<转载、转>等字则属于作者原创,欢迎转载,其版权归作者和博客园共有。
作 者:温景良 文章出处: 或