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创建数据库。

  • 相关阅读:
    jQuery属性操作,attr 和 prop的区别。笔记记录
    li 自身样式不显示?使用 overflow:hidden 导致li 前面点,圈等样式不见情况处理
    jQuery 最新版类库 和 常用的类库[jquery-1.12.3,jquery-1.7.2]下载
    Excel 中如何让下拉菜单显示汉字,但是值是数字
    Uncaught TypeError: $(...).on is not a function
    全选,全不选,反选的逻辑思路
    Linux 解决 vsftpd 读取目录列表失败的问题。
    SQL Sever 2012数据库从下载到安装完成【一步一图,带上脑子即可】
    【闲暇研究】某问道,游戏的整合记录
    Tomcat 启动后出现乱码的解决办法。
  • 原文地址:https://www.cnblogs.com/nianming/p/2145547.html
Copyright © 2011-2022 走看看