`

Entity Framework 学习初级篇--ObjectContext、ObjectQuery、ObjectStateEntry、ObjectStateMa

 
阅读更多

本节,简单的介绍EF中的 ObjectContext ObjectQueryObjectStateEntry ObjectStateManager 这个几个比较重要的类,它们都位于System.Data.Entity.dll 下的System.Data.Objects 命名空间下。在后续的章节中,我们经常会用到它们的某些方法,以便完成我们的某些操作或目的。本节,简单的说明一下以后我们可能会用到的各个类的方法, 以方便我们后续的学习。

ObjectContext 封装 .NET Framework 和数据库之间的连接。此类用作 创建 读取 更新 删除 操作的网关。

ObjectContext 类为主类,用于与作为对象(这些对象为 EDM 中定义的实体类型的实例)的数据进行交互。

ObjectContext 类的实例封装以下内容:

l           到数据库的连接,以 EntityConnection 对象的形式封装。

l           描述该模型的元数据,以 MetadataWorkspace 对象的形式封装。

l           用于管理缓存中持久保存的对象的 ObjectStateManager 对象。

ObjectContext 类的成员方法以说明如下所示:

l           AcceptAllChanges()

接受所有对该实体对象的更改

l           AddObject(string,object)

将实体对象添加到制定的实体容器中

l           ApplyPropertyChanges(string,object)

将以指派的实体对象属性的更改应用到容器中对应的原对象。

l           Attach(System.Data.Objects.DataClasses.IEntityWithKey entity)

将带主键的实体对象附加到默认的容器中

l           Attach(string,object)

将实体对象附加到指定的实体容器中

l           CreateEntityKey(string,object)

给指定的实体对象创建实体主键或如果已存在实体主键,则直接返回该实体的主键

l           CreateQuery<T>(string,params ObjectParameter[])

从给定的查询字符串创建ObjectQuery 对象。

l           DeleteObject(object)

删除指定的实体对象

l           Detach(object)

移除指定的实体对象

l           ExecuteFunction<TElement>(string,params ObjectParameter[])

对默认容器执行给定的函数。

l           GetObjectByKey(System.Data.EntityKey key)

通过主键KEYObjectStateManager 中检索对象(如果存在);否则从存储区中检索。

l           Refresh(System.Data.Objects.RefreshMode refreshMode, object entity)

按指定持久更新模式,使用指定实体的存储区数据更新ObjectStateManager 。。

l           Refresh(System.Data.Objects.RefreshMode refreshMode, System.Collections.IEnumerable collection)

按指定持久处理模式,使用指定实体集的存储区数据更新ObjectStateManager

l           SaveChanges(bool)

将所有更新持久保存到存储区中。参数是客户端事务支持所需的参数。参数为true 则在更新后自动将更改应用到ObjectStateManager 中的实体。如果为false ,则在更新后还需要调用AcceptAllChanges ()以便更新ObjectStateManager 中的实体。

l           SaveChanges()

将所有更新持久保存到存储区中

l           TryGetObjectByKey(System.Data.EntityKey,out object)

尝试从指定实体主键返回该实体

以上各个方法的具体用法,将在后面介绍。

接着,再看看有用的类ObjectQuery

ObjectQuery 有个有用的方法ToTraceString() , 这个方法用于追踪所执行的SQL 语句,通过此方法我们可以获取所执行的SQL 语句,以便我们查看、分析具体执行的SQL 语句。(类似Nhibernate 配置文件中的showsql 节)

再了解一下ObjectStateEntry

ObjectStateEntry 维护实体实例或关系实例的状态(已添加、已删除、已分离、已修改或未更改)、键值和原始值。还管理已修改属性的列表。其包含一下方法:

l           AcceptChanges

接受当前值作为原始值,并将实体标记为 Unchanged()

l             Delete

将实体标记为 Deleted() 。如果实体处于 Added()()() 状态,它将为 Detached()

l           GetModifiedProperties

返回标记为 Modified() 的属性名称。

l             SetModified

将状态设置为 Modified()

l             SetModifiedProperty

将指定的属性标记为 Modified()

接着,再看看ObjectStateManager

ObjectStateManager 用于维护对象映射、对象状态/ 标识管理以及实体实例或关系实例的持久性。

l           GetObjectStateEntries

获取给定EntityStateObjectStateEntry 集合。

l           GetObjectStateEntry

获取给定的 EntityKey 对应的 ObjectStateEntry

现在,几个重要的类简单介绍完毕。后面,我们将具体学习它们的使用。

 

 

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,  投影

代码如下:

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 等。另外,采用表达式作为输入参数的 FirstFirstOrDefault 方法不保留顺序。

如下代码:并不能达到反序排序的效果

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这个地方时,会报异常。

好,本节介绍完毕。后面将继续学习EF.
分享到:
评论

相关推荐

    ADO.NET EntityFramework 完整版教程(从初级到高级)

    ### ADO.NET Entity Framework 教程知识点概览 #### 一、Entity Framework 概述 - **背景**:Entity Framework (EF) 是 Microsoft 推出的一款 ORM (Object Relational Mapping) 工具,旨在简化数据访问层的开发,...

    Entity_Framework_学习.pdf

    Entity Framework的核心概念包括几个关键组件:ObjectContext、ObjectQuery、ObjectStateEntry和ObjectStateManager。 - ObjectContext类负责管理实体和数据库上下文之间的交互。它提供了跟踪实体状态变化和管理...

    .NET EntityFramework框架学习教程

    1. ObjectContext:这是EF的主要上下文类,它负责与数据库交互,管理对象的状态,并提供了查询数据的能力。 2. ObjectQuery:用于执行对数据库的查询,可以使用Linq-to-Entities或Entity SQL语言。 3. ...

    Entity Framework学习

    #### 四、ObjectContext、ObjectQuery、ObjectStateEntry、ObjectStateManager 类的介绍 - **ObjectContext**: 提供了与实体数据模型交互的入口点,管理实体的生命周期。 - **ObjectQuery**: 表示一个延迟执行的查询...

    Entity_Framework_学习

    #### 五、ObjectContext、ObjectQuery、ObjectStateEntry、ObjectStateManager 类的介绍 - **ObjectContext**:表示应用程序与数据源之间的连接,用于跟踪实体的状态变更并执行对数据库的操作。 - **ObjectQuery**:...

    Entity_Framework_ѧϰ.doc

    第二篇深入讲解了ObjectContext、ObjectQuery、ObjectStateEntry和ObjectStateManager类。ObjectContext是EF中的主要上下文类,它代表了一个与数据库的会话,提供了添加、删除、修改对象以及执行查询的能力。...

    Entity framework

    - **ObjectContext**:负责管理实体对象的状态,并提供方法执行CRUD操作。 - **ObjectQuery**:用于执行查询操作的对象。 - **ObjectStateEntry**:表示实体对象的状态,如添加、修改或删除状态。 - **...

    详细的Entity Framework介绍PDF格式

    初级篇主要介绍了EF的基本概念和核心组件,包括ObjectContext、ObjectQuery、ObjectStateEntry和ObjectStateManager等类,以及LINQ to Entities和Entity SQL的使用。LINQ to Entities提供了使用LINQ语言集成查询来...

    Entity_Framework_实体框架.doc

    2. **ObjectContext和ObjectQuery**:`ObjectContext`是EF早期版本中的主要上下文类,用于管理实体和数据库的交互。`ObjectQuery`则用于执行对数据的查询,它可以与`ObjectContext`配合使用来获取、筛选和排序实体。...

    Entity_Framework_实体框架

    2. **ObjectContext和ObjectQuery**:ObjectContext是Entity Framework的主要上下文类,它代表与数据库的会话,并管理实体对象。ObjectQuery则用于执行针对数据库的查询,可以使用Linq-to-Entities进行表达式查询。 ...

    Entity Framework

    3. ObjectContext、ObjectQuery、ObjectStateEntry和ObjectStateManager类:这些类是实体框架运行时的核心组成部分。ObjectContext负责管理实体对象的生命周期,以及与数据源进行交互。ObjectQuery用于执行针对...

    EntityFramework教程

    2. ObjectContext 和 ObjectQuery ObjectContext 是EF的核心组件,它代表了与数据库的连接,并提供了与实体交互的上下文。开发者可以通过ObjectContext实例来创建、读取、更新和删除实体。ObjectQuery 则是用于执行...

    Entity.Framework教程

    基础篇涉及了EF的基本概况、ObjectContext、ObjectQuery、ObjectStateEntry和ObjectStateManager类的介绍、LINQ to Entities、Entity SQL等。中级篇开始探讨更深入的话题,如EF支持复杂类型的实现、存储过程的使用、...

    EntityF资料

    ### EntityFramework资料:从入门到精通 #### EF基本概况 **Entity Framework (EF)** 是一个在 .NET 平台上的对象关系映射 (ORM) 框架,它允许开发人员通过对概念性的应用程序模型进行编程来创建数据访问层的应用...

    linq to entitties学习心得(归纳)

    - **查询构造**:首先,你需要从ObjectContext创建一个ObjectQuery实例,其中T代表你的实体类型。 - **查询编写**:然后,你可以使用C#或VB.NET的LINQ查询语法,结合ObjectQuery实例来构建查询。 - **转换**:...

Global site tag (gtag.js) - Google Analytics