zoukankan      html  css  js  c++  java
  • NBearV3 Step by Step教程——ORM进阶篇

    版本

    1.2 [2006-11-12]

    简介

    本教程在前一篇《NBearV3 Step by Step教程——ORM》的基础上,演示前文中没有涉及的实体自关联关系;及和性能相关的Attribute的设置:IndexPropertyBatchUpdate;并将详细比较和讨论NBear.Data.Gateway类中的强类型查询方法的使用和注意事项,特别是在不同的Attribute设置选项下的性能差异分析。

    注:在阅读本文之前,建议读者先阅读《NBearV3 Step by Step教程——ORM》以掌握NBearV3中有关ORM的基本知识。

    目标

    通过本教程,读者应能够更全面地掌握使用NBearV3ORM模块进行应用程序设计的过程,了解实体设计中与性能相关的重要选项,并能全面掌握NBear.Data.Gateway中各种强类型查询方法的使用。

    代码

    本教程演示创建的所有工程和代码,包含于可以从sf.net下载的NBearV3最新源码zip包中的tutorials\ORM_Adv_Tutorial目录中。因此,在使用本教程的过程中如有任何疑问,可以直接参考这些代码。

    时间

    <30分钟。

    正文

    Step 1 下载NBearV3最新版本及准备

    1.1访问http://sf.net/projects/nbear,下载NBearV3的最新版本到本地目录。

    1.2 将下载的zip文件解压至C:\,您将看到,加压后的NBearV3目录中包括:distdoccasessrctutorials等目录。其中,在本教程中将会使用的是dist目录中的所有release编译版本的dllexetutorials目录中之前的ORM基础教程。

    1.3 tutorials目录中的整个ORM_Tutorial目录复制到任意其它位置,并命名为ORM_Adv_Tutorial,我们将以ORM_Tutorial为基础,演示NBearV3中的ORM的进阶知识。

    Step 2 扩展设计实体及元数据

    2.1 ORM_Adv_Tutorial中的ORM_Tutorial.sln重命名为ORM_Adv_Tutorial.sln,并在VS2005开发环境中打开。

    2.2 EntityDesigns工程的Group.cs文件中,添加ParentID属性,并为ParentID属性添加IndexPropertyAttribute设置如下:

            [IndexProperty]
            Guid ParentID
            
    {
                
    get;
                
    set;
            }

    将属性标记为IndexProperty,表示在NBear.Tools.EntityDesignToEntity.exe生成的数据库创建脚本中,将自动为该属性创建一个单列索引。我们都理解数据库索引的作用——这将有助于改善以该属性为条件的查询性能。

    2.3 还是在Group.cs文件中,我们为Group新增一个SubGroups属性如下:

            [FkQuery("ParentID", Contained=true, LazyLoad=true)]
            Group[] SubGroups
            
    {
                
    get;
                
    set;
            }

    我们可以看到,SubGroups属性的设置方式和普通的1对多关联的属性设置方式没什么两样,但是,可以注意到,它其实是Group实体1对多关联到Group实体自己,也就是说,它是一个1对多的自关联。

    注:对于1对1自关联,也可以以类似的方式设置。但是,NBearV3还不支持多对多的自关联,也不支持一个继承体系中的类的多对多关联,例如,不支持User和LocalUser的多对多关联。

    2.4 User.cs文件和LocalUser.cs中,为UserLocalUser实体添加一个BatchUpdateAttribute如下:

        [BatchUpdate(10)]
        
    public interface User : Entity
        
    {
          \\
        }


        [BatchUpdate(
    10)]
        
    public interface LocalUser : User
        
    {
          \\
        }

    BatchUpdate这个Attribute对于该实体的查询性能将有重要影响。当使用BatchUpdate标记一个实体时,实体的Save和Delete级联操作,将在内部自动使用一个BatchGateway,以批更新方式执行。BatchUpdate的构造参数代表每多少个作为一个batch,连接数据库,并执行。举例来说,假如原来,User实体的一个实例Delete的时候,由于User实体自己,及所有User中以Contained这个Attribute标记的属性对象的数量一共有20个应该被自动Delete掉,那么,要连接20次数据库,执行20次Delete;而在设置了BatchUpdate(10)的情况下,因为每十个查询才连接一次数据库,所以,实际上,只需要连接两次数据库,每次分别发送并执行10个Delete操作。很显然,BatchUpdate对性能的改善是惊人的

    Step 3 从实体设计代码生成实体代码、实体配置文件和数据库生成脚本

    3.1 至此,所有的实体的设计就扩展完毕了。编译EntityDesigns工程。

    3.2 运行dist目录中的NBear.Tools.EntityDesignToEntity.exe工具,载入EntityDesigns工程编译生成的EntityDesigns.dll

    3.3 点击Generate Entities按钮,将生成的代码保存到Entities工程中的一个名叫Entities.cs的新代码文件。

    3.4 点击Generate Configuration按钮,将生成的代码保存到website工程下的名为EntityConfig.xml的文件中。

    3.5 点击Generate DB Script按钮,将生成的代码保存到website工程下的名为db.sql的文件,可以在某个新建的SQL Server数据库中执行这些脚本,创建对应于所有实体的数据库脚本。对于本教程而言,建议使用SQL Server 2000的查询分析器,在tempdb数据库中执行db.sql中的脚本。

    Step 4 使用Gateway进行查询

    4.1删除website工程中的Default.aspx.cs文件中原来的代码,参考tutorials\ ORM_Adv_Tutorial\website目录下的Default.aspxDefault.aspx.cs,创建Default.aspx。这些代码演示了Gateway类的大多数强类型查询方法的使用。关于Gateway支持的更多方法的介绍,可以参考doc目录下的SDK类库文档。

    4.2 运行以上代码,在输出文本框内,您将得到详细的SQL调试信息及相关说明。

    在运行结果中,大家可以注意比较以“TEXT 内容”格式出现的SQL日志,这些日志显示了何时,NBearV3的强类型查询在内部执行了什么样的SQL查询。

    有两个地方需要特别留意比较的,一个是BatchUpdate后非BatchUpdate方式下的Save和Delete时,实际执行的SQL语句;另一个是,注意LazyLoad=true和LazyLoad=false的属性,载入的时机的不同

    正文结束。

    附录

    1 关于Entity.Attach()/Detach()/IsAttached()方法的使用

    细心的读者会发现,NBearV3中,保存实体只有Save方法,而不区分Insert还是Update。那么,是如何区分一个实体什么时候该Insert,什么时候该Update的呢?

    NBear判断的是Entity.IsAttached()方法。一个刚刚new出来的实体实例,总是IsAttached() == false的,因此,当Save它时,实际会执行Insert,而一个通过Find返回的实体实例,则总是IsAttached() = true的,当保存这样的实体时,只有修改过的属性会被Update

    理解以上这一点有什么作用呢?在需要的情况下,我们可以灵活地直接调用Entity.Attach()/Detach()来修改IsAttached()的值,从而实现一些特殊需求的查询

    例如:

    假如我们想更新User对象的Status,而我们的输入参数只有Userid。如果不了解Attach()/Detach()方法,那么,只有先通过Gateway.Find方法找到ID=idUser实例,修改Status,再Save它。这至少需要两次数据库查询,一次Select,一次Update。更有效的做法是,我们可以new一个User的实例user,手动设置这个user.Attach(),修改userStatus,再Save它。这样,这个user被保存时,也只会Update IDidUserStatus属性,但是,此时,只需要一次数据库查询,就是Update

    相反的,Detach()方法,可以设置一个Attached的实体实例的IsAttached() = =false。这有什么用呢?

    例如:

    我们已经通过某些渠道得到了一个User的实例user,在某个算法中,我们可能要频繁的写User的属性,最后,才会保存这个user。如果不设置Detach(),则实体属性的每次修改都会触发Entity.OnPropertyChanged事件,这不仅意味着性能损失,也意味着,Entity.OnPropertyChanged的订阅者可能要响应很多不必要的事件变更事件。此时,理想的方法是,在频繁的写User的属性的算法执行之前,我们先Detach(),算法完成后,我们再Attach()

    2 Gateway.RegisterSqlLogger()/UnregisterSqlLogger()

    您应该已经注意到,Default.aspx.cs文件中的Page_LoadGateway.RegisterSqlLogger()的使用:

            gateway.RegisterSqlLogger(new LogHandler(WriteLine));

    对应于注册一个SqlLogger,我们也可以调用UnregisterSqlLogger()来注销一个SqlLogger

    这两个方法对于调试应用程序的运行和程序性能的优化非常重要,建议大家在开发中一定要注意使用,从而有效监视NBear提供的强类型外衣下的,真正的程序和数据库的交互细节。

    //本文结束

  • 相关阅读:
    adoQuery对象池
    面向對象囈語
    TDataSetProvider 元件的設定
    Midas的三種調用遠程方法的方式
    線程池
    数据库连接池类
    remobject 簡介
    多層開發注重效率的注意點
    修改的一个导出DataSet到xls的单元
    Git 换行符检查 CRLF 与 LF
  • 原文地址:https://www.cnblogs.com/teddyma/p/550711.html
Copyright © 2011-2022 走看看