• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录

Dotnet之旅

  • 博客园
  • 联系
  • 订阅
  • 管理

公告

View Post

实践ORM,创建基于Grove的.NET应用程序

 


就目前大多数软件开发项目的数据都存储在关系型数据库中,开发时要求开发人员对SQL语句语法以及规则等必须很熟悉,而很多情况下,开发人员需要手写SQL语句,同时还得考虑事务处理,逻辑分析等等问题,导致整个项目中的SQL语句到处都是,对程序的可读性,可维护性都带来了阻碍,同时,当新项目加入时,很多地方又不得不重新coding一些大而复杂的相关代码,这样又何来可重用之谈呢?另外对程序员要求就高了,程序调试起来又麻烦了,又得调试程序,又得调试SQL语句,很多时候SQL语句包含了一些逻辑部分的处理,这些都是非常不科学的。

为了提高项目的灵活性,可重用性等,就必须提到OR-M(对象角色建模),个人认为OR-M的作用是解耦,在原本复杂的系统中加入OR-M一层,使得系统变得更容易维护和升级,比如在之前的系统中,更改了一个数据库字段,则相应用到该字段的所有地方都随之而改动,这有可能带来很大的工作量,而应用之后,业务逻辑层的代码几乎不用改动,相应的,调用的地方也不用改动,改动的也许仅仅只有映射的那些地方。由于本文介绍的重点不是OR-M,所以关于OR-M的具体信息见最后的参考资料。

目前,针对.NET下的ORM方式有很多,大概归纳有三种,一是实体类映射方式,二是透过XML来描述,三是XML和实体类一起用(比如MS的ObjectSpaces)

本文演示了如何使用Grove Tool Kit来创建一个基于Grove的简单Web应用程序。Grove是一套基于Microsoft .NET Framework的可重用开发组件,支持多种不同数据库项目,提供标准的二层,三层及多层等开发框架。

简介
Grove Develop Component Kit 包括 Grove Develop Component 和 Grove Tool Kit两部分;
Grove Develop Component是一套基于Microsoft .NET Framework的可重用开发组件,支持多种不同数据库项目,提供标准的二层,三层及多层等开发框架。
Grove Develop Component结合可复用面向对象软件开发原理(泛指设计模式),注重提高软件开发中的代码重用率,并使软件开发架构清晰,有利于加快软件开发速度,减低软件维护成本。
Grove Tool Kit 是针对Grove Develop Component提供的一套.NET Develop Environment的外接程序 ,能够帮助预览或生成依赖于Grove组件的可重用代码,包括数据库映射的实体类(Entity Definition Class) ,XML实体描述(XML Definition for data store)等。
Grove Tool Kit最大的特点在于可以通过工具本身调试,关联多表之间的关系,并生成多表查询的映射实体或XML映射描述。

安装
安装GroveKit要求VS.NET 2002或2003及.NET Framework 1.0或1.1,本文以.NET Framework 1.1和VS.NET 2003为例。
GroveKit的安装包(GroveKit.zip),您可以从http://grove.91link.com 获得。
安装步骤:
1. 解压缩GroveKit.zip,执行安装
2. 执行桌面上的Grove Install以完成安装任务

创建基于Grove的Web项目

在GroveKit安装结束后,打开VS.NET,在VS.NET的启动画面上,您会看到Grove Develop Kit的标志,表示GroveKit已被正确安装。

本文将以C# ASP.NET项目为例,项名WebApp1,操作系统 Windows 2000,数据库SQL Server 2000,数据库实例名:WebApp1,表结构定义如下
Customers(表名)
CustomerID int(4) PK
CustomerName varchar(50)
CustomerDesc varchar(200)

Addresses(表名)
AddressID int(4) PK
CustomerID int(4)
Address varchar(200)

1)在VS.NET中,打开“文件->新建->项目”,在Visual C#项目选择ASP.NET WEB应用程序,确定后生成WebApp1项目,在项目中添加文件夹Entities(实体),Managers(Façade层),EntityDB(数据库层),并添加对Grove.dll的引用,Grove.dll位于GroveKit的安装路径下,您也可以通过.NET Configuration将Grove添加到程序集缓存中。

2)在VS.NET中,打开“工具->Grove Tool Kit”,在GroveToolKit中设置数据库连接属性,并保存。

图1.设置数据库连接串

3)在当前项目路径C:\Inetpub\wwwroot\WebApp1下建立LogFiles文件夹,并配置当前Web项目的web.config(在</configuration>之前加入以下配置)

<appSettings>

<add key="DBConnString" value="Server=localhost;Uid=sa;Pwd=sa;Database=WebApp1" />

<add key="LogPath " value="c:\inetpub\wwwroot\WebApp1\LogFiles" />

</appSettings>

4)在VS.NET解决方案资源管理器中选中Entities,并在GroveToolKit中选择表名,点击GroveToolKit的toolbar中的Preview Entity Class按钮,出现该表的实体映射类预览窗口。

图2. 预览实体映射类

5)检查当前预览的实体类的namespace,此处应该改为WebApp1.Entities,点击生成文件按钮,该实体类将被生成到解决方案资源管理器当前选中的路径下。

6)重复4,5步骤生成其他表的映射实体类。

 

Customer.cs
using System;

using Grove.DataObject;

[DataTable("Customers")]

public class Customer

{

int _CustomerID;

string _CustomerName;

string _CustomerDesc;

 

[KeyField("CustomerID")]

public int CustomerID

{

get{return this._CustomerID;}

set{this._CustomerID=value;}

}

[DataField("CustomerName")]

public string CustomerName

{

get{return this._CustomerName;}

set{this._CustomerName=value;}

}

[DataField("CustomerDesc")]

public string CustomerDesc

{

get{return this._CustomerDesc;}

set{this._CustomerDesc=value;}

}

}

Address.cs
using System;

using Grove.DataObject;

[DataTable("Addresses")]

public class Address

{

int _AddressID;

int _CustomerID;

string _Address;

 

[KeyField("AddressID")]

public int AddressID

{

get{return this._AddressID;}

set{this._AddressID=value;}

}

[DataField("CustomerID")]

public int CustomerID

{

get{return this._CustomerID;}

set{this._CustomerID=value;}

}

[DataField("Address")]

public string CustomerAddress

{

get{return this._Address;}

set{this._Address=value;}

}

}

代码1.实体映射类


7)在当前项目的EntityDB下添加CustomerDB类,该类负责对Customer的数据库操作,包括添加,删除,修改等操作。

       8)重复7,完成AddressDB类。

 

CustomerDB.cs

     using System;

     using WebApp1.Entities;

     using Grove;

     using Grove.DataObject;

    

     public class CustomerDB

     {

         public CustomerDB()

         {

         }

         public void Insert(Customer c)

         {

              IObjectOperator oo=ObjectOperatorFactory.GetObjectOperator();

              oo.BeginTranscation();

              try

              {

                   oo.InsertObject(c);

                   oo.Commit();

              }

              catch(System.Exception e)

              {

                   oo.Rollback();

                   throw e;

              }

              oo.Dispose();

         }

         public void Delete(Customer c)

         {

              IObjectOperator oo=ObjectOperatorFactory.GetObjectOperator();

              oo.BeginTranscation();

              try

              {

                   oo.RemoveObject(c);

                   oo.Commit();

              }

              catch(System.Exception e)

              {

                   oo.Rollback();

                   throw e;

              }

              oo.Dispose();         

         }

         public void Update(Customer c)

         {

              IObjectOperator oo=ObjectOperatorFactory.GetObjectOperator();

              oo.BeginTranscation();

              try

              {

                   oo.UpdateObject(c);

                   oo.Commit();

              }

              catch(System.Exception e)

              {

                   oo.Rollback();

                   throw e;

              }

              oo.Dispose();                       

         }

         public EntityData SelectAll()

         {

              IObjectOperator oo=ObjectOperatorFactory.GetObjectOperator();

              IObjectQuery oq=oo.NewQuery(typeof(Customer));

              EntityData customers=new EntityData();

              oq.Execute(customers);

              oo.Dispose();

              return customers;

         }

     }

AddressDB.cs

     using System;

     using WebApp1.Entities;

     using Grove;

     using Grove.DataObject;

 

     public class AddressDB

     {

         public AddressDB()

         {

         }

         public void Insert(Address a)

         {

              IObjectOperator oo=ObjectOperatorFactory.GetObjectOperator();

              oo.BeginTranscation();

              try

              {

                   oo.InsertObject(a);

                   oo.Commit();

              }

              catch(System.Exception e)

              {

                   oo.Rollback();

                   throw e;

              }

              oo.Dispose();

         }

         public void Delete(Address a)

         {

              IObjectOperator oo=ObjectOperatorFactory.GetObjectOperator();

              oo.BeginTranscation();

              try

              {

                   oo.RemoveObject(a);

                   oo.Commit();

              }

              catch(System.Exception e)

              {

                   oo.Rollback();

                   throw e;

              }

              oo.Dispose();         

         }

         public void Update(Address a)

         {

              IObjectOperator oo=ObjectOperatorFactory.GetObjectOperator();

              oo.BeginTranscation();

              try

              {

                   oo.UpdateObject(a);

                   oo.Commit();

              }

              catch(System.Exception e)

              {

                   oo.Rollback();

                   throw e;

              }

              oo.Dispose();                       

         }

         public EntityData SelectAll()

         {

              IObjectOperator oo=ObjectOperatorFactory.GetObjectOperator();

              IObjectQuery oq=oo.NewQuery(typeof(Address));

              EntityData addresses=new EntityData();

              oq.Execute(addresses);

              oo.Dispose();

              return addresses;

         }

     }

代码2.数据库类







9) 在当前项目的Managers下添加CustomerManager类及AddressManager类,Managers层属于商业逻辑层,负责对实体数据库操作的再一次封装。

       在商业逻辑层,此处将类构造函数定义成私有,实现Singleton模式。

      

CustomerManager.cs

     using System;

     using Grove;

     using WebApp1.Entities;

     using WebApp1.EntityDB;

 

     public class CustomerManager

     {

         private CustomerManager()

         {

         }

         public static void AddNewCustomer(Customer c)

         {

              CustomerDB db=new CustomerDB();

              db.Insert(c);

         }

         public static void DeleteCustomer(Customer c)

         {

              CustomerDB db=new CustomerDB();

              db.Delete(c);

         }

         public static void UpdateCustomer(Customer c)

         {

              CustomerDB db=new CustomerDB();

              db.Update(c);

         }

         public static EntityData GetAllCustomers()

         {

              CustomerDB db=new CustomerDB();

              return db.SelectAll();

         }

     }

AddressManager.cs

     using System;

     using Grove;

     using WebApp1.Entities;

     using WebApp1.EntityDB;

 

     public class AddressManager

     {

         private AddressManager()

         {

 

         }

         public static void AddNewAddress(Address a)

         {

              AddressDB db=new AddressDB();

              db.Insert(a);

         }

         public static void DeleteAddress(Address a)

         {

              AddressDB db=new AddressDB();

              db.Delete(a);

         }

         public static void UpdateAddress(Address a)

         {

              AddressDB db=new AddressDB();

              db.Update(a);

         }

         public static EntityData GetAllAddresses()

         {

              AddressDB db=new AddressDB();

              return db.SelectAll();

         }

     }

代码3.Façade层定义

       10)添加Customer和Address的添加页面,在ASPX页面后置类aspx.cs中添加对Façade层的引用实现对实体数据的插入,修改,删除等功能。

       简单示例:

              Customer c=new Customer();

              c.CustomerName=”创特软件”;

              c.CustomerDesc=”http://www.tryitsoft.com”;

              CustomerManager.AddNewCustomer(c );

       11)在Customers和Addresses表中,Addresses表中的CustomerID为主表Customers的PK(主键),所以实体类Address.cs的属性CustomerID,绑定的DataField()可以改为ForeignKeyField(),在对某个Customer操作的时候,可以通过以下方式得到该客户的所有地址。

 

ArrayList addresses=new ArrayList();

IObjectOperator oo=ObjectOperatorFactory.GetObjectOperator();

oo.RetrieveChildObjects(c.CustomerID,addresses,typeof(Address));

 

       12)当我们需要快速开发,不需要考虑三层或多层应用的时候,实现实体类的自身持久化就很有必要,要实现实体类的自身持久化,必须继承Grove.DataObject.EntityClassBase。

简单示例:

              Customer c=new Customer();

              c.CustomerName=”创特软件”;

       c.CustomerDesc=”http://www.tryitsoft.com”;

       c.Insert();

       13)***关于实体映射多表关系查询。点击GroveToolKit的toolbar中的Build Relationship Query按钮,出现多表关系查询向导,选择Entity Class点击下一步,出现Relation Query Builder窗口,在窗口的下半部分右击选择”Add Table…”或者在窗口的toolbar上点击Add Existing Table按钮,出现添加表窗口,分别添加表Customers和Addresses

 

图3. 构造关系实体映射

       在图3中,点击Customers表的字段部分(按住鼠标左键)拖动到Addresses表的字段区域,并放开鼠标左键,出现两表关系窗口

图4.表间关系属性

       在图4中选择Addresses表的CustomerID列后,点击OK,如果需要指定两表之间是左关联、右关联或者全外关联,请选择Include rows下的选项。

图5.关系生成后

       在图5中,右击Customers表选择Select all columns或选择Table Property后选择需要显示的列。

图6.选择表的显示列

 

       在图5中,选择Addresses表需要显示的列,然后点击当前窗口toolbar上的执行按钮,如果正确执行,执行结果将会显示在当前窗口,现在,点击toolbar上的Preview relation query class按钮预览关系实体映射类。

 

CustomersRelationQuery.cs

     using System;

     using Grove.DataObject;

     [RelationTable("CustomersRelationQuery",BeginWithTable="Customers")]

     public class CustomersRelationQuery

     {

         [RelationReflect("Customers","Addresses")]

         [RelationField("CustomerID","AddressID")]

         public string Relationship_1

         {

              get{return "[Customers].[CustomerID]=[Addresses].[AddressID]";}

         }

 

         int _CustomerID;

         [DataField("CustomerID",TableName="Customers")]

         public int CustomerID

         {

              get{return this._CustomerID;}

              set{this._CustomerID=value;}

         }

         string _CustomerName;

         [DataField("CustomerName",TableName="Customers")]

         public string CustomerName

         {

              get{return this._CustomerName;}

              set{this._CustomerName=value;}

         }

         string _CustomerDesc;

         [DataField("CustomerDesc",TableName="Customers")]

         public string CustomerDesc

         {

              get{return this._CustomerDesc;}

              set{this._CustomerDesc=value;}

         }

         string _Address;

         [DataField("Address",TableName="Addresses")]

         public string Address

         {

              get{return this._Address;}

              set{this._Address=value;}

         }

     }

代码4.关系映射实体类




操作该关系映射实体类,简单示例:

              IObjectOperator oo=ObjectOperatorFactory.GetObjectOperator();

        IObjectQuery oq=oo.NewQuery(typeof(CustomersRelationQuery));

        oq.Filter=”this.CustomerName=‘创特软件’”;

        oq.Execute(result);

       当前Grove支持多表关系查询,包括表间LEFT JOIN ,RIGHT JOIN ,FULL JOIN以及默认的INNER JOIN等。

支持子查询IN,简单示例:

              IObjectOperator oo=ObjectOperatorFactory.GetObjectOperator();

        IObjectQuery oq=oo.NewQuery(typeof(Address));

        oq.Filter=”Customer.CustomerID.Contains(this.CustomerID)”;

        oq.DeclareCollection(“Customer.CustomerID”,”Customer.CustomerID>1000”);

        result=oq.Execute(typeof(Customer));

说明:以上查询表示的SQL形式为select * from Addresses where CustomerID in (select CustomerID from Customers where Customers.CustomerID>1000)

 

       14)基于XML描述的Grove应用请参考Grove帮助(CHM格式),Grove帮助可以从GroveKit安装目录得到或者执行toolbar的帮助按钮启动。

 

三层架构原理

 

各层之间的关系是数据表示层负责封装数据,作为数据存取层的调用参数,返回结果;商业逻辑层调用数据存取层处理的结果;商业逻辑层和ASP.NET(一般为ASPX页面的后置类.aspx.cs)通信。ASPX的结果从商业逻辑层获取,ASPX需要做调用商业逻辑层的动作。例如Customer的插入,即使在数据存取层存在这样的一个方法,也不能由ASPX直接调用。必须在商业逻辑层中再封装一次.这样做的目的在于使结构简单,清晰。数据存取层只负责操作数据库(实质是由Grove组件操作)。商业逻辑层只做逻辑(得到相应操作或返回的数据),处理相应的逻辑,而数据表示层只负责数据的封装,或是把ASPX页面的参数封装,作为商业逻辑层的参数传入商业逻辑层,并由商业逻辑层做相应处理,并转交数据存取层做实质上的数据操作。

 

基于Grove的多层开发结构图

 

 

 

 

 

 

 

 

 

 

结束语

       通过上面的示例,相信您已经掌握了怎样创建一个基于Grove的.NET的Web应用程序,包括实体映射类的一些方法,Façade层的一些定义,及相关DAO层的一些重用方法,这些方法已经创建了您的Web应用程序,下一步,您可以通过Microsoft Application Center Test来测试您的程序。

 

参考资料

       关于Grove的详细信息,支持站点已经为您提供了一些相关帮助

       http://grove.91link.com

       关于对象角色建模ORM,请参考
       http://www.microsoft.com/china/msdn/vstudio/technical/articles/orm.asp

posted on 2006-12-26 09:28  浮游  阅读(527)  评论(0)    收藏  举报

刷新页面返回顶部
 
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3