zoukankan      html  css  js  c++  java
  • Entity Framework 4 in Action读书笔记——第三章:查询对象模型基础(2)

    三、对类进行查询

    因为数据库对EDM是完全抽象的,你可以完全忽略底层的数据库结构对类进行查询。EF使用映射信息转换查询成SQL。工作流如下:

    image

    类和数据库之间的抽象不难理解。如果一个属性和数据表列的名称不匹配,你仍然可以在你的查询里使用属性名——这在类查询时非常明显。使用LINQ to Entities,你不太可能输入错误的名称,因为VS的智能提示给你提示正确的名称。更重要的是,如果你键入一个不正确的属性名,编译器会抛出一个异常。

    其他情况可以导致数据库和对象模型的不同。Customers和Suppliers有自己的类,但只有一个表存储它们的数据。再次,你对这些实体类进行查询而不是对Company表。

    此外,我们已经把地址信息组合成一个复杂类型。当查询时,它们像类型的一部分进行访问,然而在数据库中它们是清晰地列。

    起初,这些差异可能会蒙蔽你的眼睛,尤其是你熟悉关系模型。但是经过一些实践,你会发现这种方式的查询比SQL查询更直观和有效。类表示业务场景比关系模型更有意义,结果是对类查询比SQL查询更面向业务。更重要的时,类之间的错综复杂的关系由EF处理,你不需要关心数据的物理关联。

    四、从数据库中检索数据

    当你执行一个查询,LINQ提供托管实体集解析查询,并创建一个命令树。因为你正在写对类的查询,命令树代表概念上的查询。对象服务将命令树传给Entity Client,在映射和存储文件的帮助下,转换命令树为本地SQL命令。Entity Client使用ADO.NET 提供程序(在connectionString属性的provider节指定)启动SQL对数据库查询,并获得结果。然后查询结果形成表格的形式反映对象模型的结构。最后数据返回到对象服务层。下图说明了这一过程:

    E{MYB}}3E%V{IJ2A3)AL_47

    在添加scalar, complex和 reference属性之后,处理集合属性之前,上下文触发ObjectMaterialized事件。这个事件接受正在具体化的实体,在对象返回给程序之前允许你执行一些逻辑。下面的代码向你展示如何使用这一事件。

    public OrderITEntities()
    {
        ctx.ObjectMaterialized +=
        new ObjectMaterializedEventHandler(ctx_ObjectMaterialized);
    }
    void ctx_ObjectMaterialized(object sender, ObjectMaterializedEventArgs e)
    {
        var o = entity as Order;
        //any logic
    }

    五、捕获生成的SQL

    虽然实体框架生成SQL代码,但是你不能假设代码都是好的。你必须始终确保执行生成的代码不需要太多的数据库资源。有时候,生成的查询太过繁重和复杂,你可以通过存储过程或者手动写SQL获得更好的性能。

    检查SQL最简单的方法是使用 profiler工具。使用这个工具,您可以监视所有对数据库执行的语句,然后分析需要细化或完全替代的语句。通常,这种监测需要高级的数据库权限,有时你并没有这种权限。幸运的是,对象服务层使用ObjectSet<T>类的ToTraceString方法可以帮助你。下面是怎么使用它

    var result = ctx.Orders.Where(o => o.Date.Year == DateTime.Now.Year);
    var SQL = (result as ObjectQuery).ToTraceString();

    六、查询何时执行?

    通常来说,LINQ查询当程序代码访问数据时执行。每次LINQ to Entities执行查询时,EF访问数据库并取回数据。当把数据从记录转换成对象时,LINQ to Entities会扫描内存中看对象是否存在,如果存在,就返回内存中的对象,如果不存在,就将记录转换成对象,放入内存并返回。

    让我们看一个例子。假设你必须遍历两次查询结果,如下:

    var result = LINQToEntitiesQuery;
    foreach(var o in result)
    {
         ...
    }
    foreach(var o in result)
    {
         ...
    }

    每次foreach执行时,就会触发对数据库的往返操作。上下文不关心你是否已经执行了相同的查询。

    如果不是简单的查询所有的订单,而是更复杂的查询,两次执行表示存在严重的性能问题。简单的解决办法是第一次强制执行,然后把对象下载到内存中。然后在内存中遍历集合,这样就不用对数据库来回访问两次了。下面是代码:

    var result = LINQToEntitiesQuery.ToList();
    foreach(var o in result)
    {
         ...
    }
    foreach(var o in result)
    {
         ...
    }

    这个方法不仅适用于返回对象列表,还适用于返回一个单独的对象。EF使查询返回一个对象和一个集合没有什么区别。

    七、从上下文管理数据库

    ObjectContext类由四个有趣的方法让你操作数据库结构:

    CreateDatabase—使用连接字符串和SSDL信息创建数据库

    CreateDatabaseScript—使用SSDL信息生成数据库脚本

    DatabaseExists—验证指定连接字符串的数据库是否存在

    DeleteDatabase—使用指定的连接字符串删除数据库

    当创建一个应用程序不创建安装包时,这些方法很有用。当程序启动时,如果数据库不存在可以使用DatabaseExists和CreateDatabase创建数据库。

  • 相关阅读:
    盒子垂直水平居中
    Sahi (2) —— https/SSL配置(102 Tutorial)
    Sahi (1) —— 快速入门(101 Tutorial)
    组织分析(1)——介绍
    Java Servlet (1) —— Filter过滤请求与响应
    CAS (8) —— Mac下配置CAS到JBoss EAP 6.4(6.x)的Standalone模式(服务端)
    JBoss Wildfly (1) —— 7.2.0.Final编译
    CAS (7) —— Mac下配置CAS 4.x的JPATicketRegistry(服务端)
    CAS (6) —— Nginx代理模式下浏览器访问CAS服务器网络顺序图详解
    CAS (5) —— Nginx代理模式下浏览器访问CAS服务器配置详解
  • 原文地址:https://www.cnblogs.com/nianming/p/2145547.html
Copyright © 2011-2022 走看看