ADO.NET Entity Framework 学习初级篇3-- LINQ TO Entities

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.    将查询结果返回到客户端。

一、Linq To Entities简单查询

下面将介绍简单的Linq To Entities查询,相关的查询语法可以使用基于表达式或基于方法的语法。本节使用的TestDriver.Net配合Nunit2.4进行 测试

1,  投影

代码如下:
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Data.Objects;
  5. using NUnit.Framework;
  6. namespace NorthWindModel
  7. {
  8.     [TestFixture]
  9.     public class TestEFModel
  10.     {
  11.         [Test]
  12.         public void Select()
  13.         {
  14.             using (var edm = new NorthwindEntities())
  15.             {
  16.                 //基于表达式的查询语法
  17.                 ObjectQuery<Customers> customers = edm.Customers;
  18.                 IQueryable<Customers> cust1 = from c in customers
  19.                                               select c;
  20.                 Assert.Greater(cust1.Count(), 0);
  21.                 //使用ObjectQuery类的ToTraceString()方法显示查询SQL语句
  22.                 Console.WriteLine(customers.ToTraceString());
  23.             }
  24.         }
  25.     }
  26. }
复制代码
输出:
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,  条件限制
  1. using (var edm = new NorthwindEntities())
  2. {
  3.     //基于表达式的查询语法
  4.     ObjectQuery<Customers> customers = edm.Customers;
  5.     IQueryable<Customers> cust1 = from c in customers
  6.                                   where c.CustomerID == "ALFKI"
  7.                                   select c;
  8.  
  9.     Assert.AreEqual(cust1.Count(), 1);
  10.     foreach (var c in cust1)
  11.         Console.WriteLine("CustomerID={0}", c.CustomerID);
  12.              
  13.     //基于方法的查询语法
  14.     var cust2 = edm.Customers.Where(c => c.CustomerID == "ALFKI");
  15.     Assert.AreEqual(cust2.Count(), 1);
  16.     foreach (var c in cust2)
  17.           Console.WriteLine("CustomerID={0}", c.CustomerID);
  18. }
复制代码
3,  排序和分页

在使用Skip和Take方法实现分页时,必须先对数据进行排序,否则将会抛异常。
  1. using (var edm = new NorthwindEntities())
  2. {
  3. //基于表达式的查询语法
  4.         ObjectQuery<Customers> customers = edm.Customers;
  5.         IQueryable<Customers> cust10 = (from c in customers
  6.                                         orderby c.CustomerID
  7.                                         select c).Skip(0).Take(10);
  8.           Assert.AreEqual(cust10.Count(), 10);
  9.           foreach (var c in cust10)
  10.               Console.WriteLine("CustomerID={0}", c.CustomerID);
  11.    
  12. //基于方法的查询语法
  13.     var cust = edm.Customers.OrderBy(c => c.CustomerID).Skip(0).Take(10);
  14.     Assert.AreEqual(cust.Count(), 10);
  15.     foreach (var c in cust)
  16.         Console.WriteLine("CustomerID={0}", c.CustomerID);
  17.   }
复制代码
4,  聚合

可使用的聚合运算符有Average、Count、Max、Min 和 Sum。
  1. using (var edm = new NorthwindEntities())
  2.   {
  3.       var maxuprice = edm.Products.Max(p => p.UnitPrice);
  4.       Console.WriteLine(maxuprice.Value);
  5. }
复制代码
5,  连接

可以的连接有Join 和 GroupJoin 方法。GroupJoin组联接等效于左外部联接,它返回第一个(左侧)数据源的每个元素(即使其他数据源中没有关联元素)。
  1. using (var edm = new NorthwindEntities())
  2.     {
  3.       var query = from d in edm.Order_Details
  4.                   join order in edm.Orders
  5.                   on d.OrderID equals order.OrderID
  6.                   select new
  7.                     {
  8.                         OrderId = order.OrderID,
  9.                         ProductId = d.ProductID,
  10.                         UnitPrice = d.UnitPrice
  11.                     };
  12.         foreach (var q in query)
  13.         Console.WriteLine("{0},{1},{2}",q.OrderId,q.ProductId,q.UnitPrice);
  14. }
复制代码
其他一些方法等就不多说了,和Linq to SQL 基本上是一样的。
TOP
二、LINQ to Entities 查询注意事项

l          排序信息丢失

如果在排序操作之后执行了任何其他操作,则不能保证这些附加操作中会保留排序结果。这些操作包括 Select 和 Where 等。另外,采用表达式作为输入参数的 First 和 FirstOrDefault 方法不保留顺序。

如下代码:并不能达到反序排序的效果
  1. using (var edm = new NorthwindEntities())
  2. {
  3.     IQueryable<Customers> cc = edm.Customers.OrderByDescending(c => c.CustomerID).Where(c => c.Region != null).Select(c => c);
  4.     foreach (var c in cc)
  5.           Console.WriteLine(c.CustomerID);
  6. }
复制代码
l          不支持无符号整数

由 于 实体框架不支持无符号整数,因此不支持在 LINQ to Entities 查询中指定无符号整数类型。如果指定无符号整数,则在查询表达式转换过程中会引发 NotSupportedException异常,并显示无法创建类型为“结束类型”的常量值。此上下文仅支持基元类型(“例如 Int32、String 和 Guid”)。

如下将会报异常的代码:
  1. using (var edm = new NorthwindEntities())
  2. {
  3.       uint id = UInt32.Parse("123");
  4.       IQueryable<string> produt = from p in edm.Products
  5.                                   where p.UnitPrice == id
  6.                                   select p.ProductName;
  7.       foreach (string name in produt)
  8.             Console.WriteLine(name);
  9. }
复制代码
上面的代码中,由于id是uint而不是Int32,String,Guid的标量类型,所以在执行到where p.UnitPrice ==id这个地方时,会报异常。

l          不支持引用非标量闭包

不支持在查询中引用非标量闭包(如实体)。在执行这类查询时,会引发 NotSupportedException 异常,并显示消息“无法创建类型为“结束类型”的常量值。此上下文中仅支持基元类型(‘如 Int32、String 和 Guid’)

如下将会报异常的代码:
  1. using (var edm = new NorthwindEntities())
  2. {
  3.         Customers customer = edm.Customers.FirstOrDefault();
  4.         IQueryable<string> cc = from c in edm.Customers
  5.                                 where c == customer
  6.                                 select c.ContactName;
  7.         foreach (string name in cc)
  8.               Console.WriteLine(name);
  9. }
复制代码
上面的代码中,由于customer是引用类型而不是Int32,String,Guid的标量类型,所以在执行到where c==customer这个地方时,会报异常。

好,本节介绍完毕。后面将继续学习EF。(文/ ♂风车车.Net )

你可能感兴趣的:(ADO.NET Entity Framework 学习初级篇3-- LINQ TO Entities)