Grove——.NET中的ORM实现

 

Grove——.NET中的ORM实现

发布日期: 6/30/2005 | 更新日期: 6/30/2005

作者:林学鹏

ORM的全称是Object Relational Mapping,即对象关系映射。它的实质就是将关系数据(库)中的业务数据用对象的形式表示出来,并通过面向对象(Object-Oriented)的方式将这些对象组织起来,实现系统业务逻辑的过程。在ORM过程中最重要的概念是映射(Mapping),通过这种映射可以使业务对象与数据库分离。从面向对象来说,数据库不应该和业务逻辑绑定到一起,ORM则起到这样的分离作用,使数据库层透明,开发人员真正的面向对象。图 1简单说明了ORM在多层系统架构中的这个作用。

art\grove_001.jpg

图1:ORM在多层系统架构中的作用

目前大多数项目或产品都使用关系型数据库实现业务数据的存储,这样在开发过程中,常常有一些业务逻辑需要直接用写SQL语句实现,但这样开发的结果是:遍地布满SQL语句。这些高藕合的SQL语句给系统的改造和升级带来很多无法预计的障碍。为了提高项目的灵活性,特别是快速开发,ORM是一个不错的选择。举个简单的例子:在使用ORM的系统中,当数据库模型改变时,不再需要理会逻辑代码和SQL语句中涉及到该模型的所有改动,只需要将该模型映射的对象稍作改动,甚至不做改动就可以满足要求。

一、ORM的工具实现:Grove

优秀的ORM工具不仅可以帮助我们很好的理解对象及对象的关系,而且工具本身会帮助我们维护这些关系。基于这个理念,我设计了基于.NET的ORM工具——Grove ORM Development Toolkit。

Grove ORM Development Toolkit包含Grove和Toolkit两部分内容。Grove为ORM提供对象持久、关系对象查询、简单事务处理、简单异常管理等功能。数据持久包括一些对象的Insert、Delete、Update、Retrieve等功能,关系对象查询则提供一些基于对象的复杂关系查询,包括对应到数据库功能的子查询、关联查询(JOIN)、函数支持(count、avg、max、min)、聚合等。Toolkit是基于VS.NET 2002/2003的VSIP开发的外接程序,职责是帮助开发人员快速映射关系数据库中的业务模型到符合Grove要求的映射实体类,以及映射数据库中复杂关系查询到Grove要求的关系映射实体,暂时只提供C#支持。图 2是Grove内部类实现关系图。

art\grove_002.jpg

图 2: Grove内部类实现关系图

在ORM实现的前期工作中,为了实现屏蔽各种数据库之间的操作差异,我们需要定义数据操作公有接口,封装基本的数据库Insert,Update,Delete,Query等操作。

public interface IDbOperator
{
int ExecNonQuery(string cmdText);
int ExecDataSet(string cmdText,DataSet entity); 
object ExecScalar(string cmdText);
…
}

再定义一个数据库操作工厂类,实现各种不同类型数据的适配。

public abstract class DbOperatorFactory:IDbOperator

然后实现各种数据库的操作类,以SQLServer为例。

internal class SqlDbOperator:DbOperatorFactory

完成后,就是ORM主角——实体(Entity)的实现。ORM中实体的定义可以通过实体类自身包含数据模型元数据的方式实现,也可以通过定义XML的元描述实现。下面讲述了通过实体类自身映射的实现。

实体(Entity)是实际业务数据的载体,包含业务数据模型的元描述,可以直接由数据库中的某张表或视图生成,也可以根据需要手工创建。.NET中提供了System.Attribute,该类包含访问和测试自定义属性的简便方法。.NET Framework预定义了一些属性类型并使用它们控制运行时行为。我们可以通过继承System.Attribute基类自定义用于描述实体对象映射时所需要的数据模型元数据,包括表名,字段名,字段长度,字段类型等一些常用的数据。

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct)]
public class DataTableAttribute : Attribute

AttributeUsage用来表示该自定义属性可以被绑定在什么样的对象上,这里表示应用在Class或者Struct之上。

抽象一些具有相同特征的属性,使之成为自定义属性的基类。

[AttributeUsage(AttributeTargets.Property)]
public class BaseFieldAttribute:Attribute

定义一般字段所需要的自定义属性类。

[AttributeUsage(AttributeTargets.Property)]
public class DataFieldAttribute : BaseFieldAttribute

定义关键字字段所需的自定义属性类。

[AttributeUsage(AttributeTargets.Property)]
public class KeyFieldAttribute : BaseFieldAttribute

定义外键字段所需要的自定义属性类。

[AttributeUsage(AttributeTargets.Property)]
public class ForeignKeyFieldAttribute : BaseFieldAttribute

在以上自定义属性类完成后,我们需要一个用于访问实体在运行期绑定的自定义属性及属性数据的一个Help类。

internal class TypeHelper

实体定义完成后,我们需要根据实体类中绑定的自定义属性构造出运行期需要的SQL语句,为了收集实体类定义中的数据结构描述,我们需要定义一个类来说明实体在运行期所引用到的所有关于数据持久的信息,包括关键字字段,外键字段,一般字段等。

internal class TypeInfo

同时需要一个字段元数据描述类,描述字段在数据库中的名称,大小,是否可为空,列类型等信息。

internal class ColumnInfo

以上条件具备后,我们需要定义一个解析类,负责转换数据的程序类型到数据库字段类型,并且构造出Insert,Update,Delete,Query等操作所需要的SQL语句。

internal class SqlEntityParser

将上面的操作组合起来就是实体类对象操作员。

public class ObjectOperator

实现新增一个记录到数据库中,就是创建了一个新的实体对象,并交由对象操作员进行持久化。

public void Insert(object o)
{
TypeInfo info1=new TypeInfo(o.GetType());//根据实例或者实体描述信息
SQLCommand sc=info1.BuildInsertCommand(o);//构造SQL命令对象
DbOperator.Parameters=sc.Parameters;//赋值SQL命令所需的参数
DbOperator.ExecNonQuery(sc.CommandText);//执行SQL命令
}

这里的SQLCommand对象封装了SQL命令处理时所需要的一些值,包含SQL语句,命令参数(Parameter)等。

二、Grove在开发中的实际应用

安装Grove Kit要求Visual Studio 2003 及.NET Framework 1.1支持。从Grove网站下载安装包之后,解压缩GroveKit.zip,执行安装。

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

2.1生成映射实体类

本文将以C# 项目为例解释Grove在开发中的具体应用。项目名WebApp1,操作系统 Windows 2000,数据库SQL Server 2000,数据库实例名:WebApp1,表结构定义如下:

表名字段

Customers

CustomerID int(4) PK

CustomerName varchar(50)

CustomerDesc varchar(200)

Status tinyint

Addresses

AddressID int(4) PK

CustomerID int(4) FK

Address varchar(200)

1.

在VS.NET中,打开“文件->新建->项目”,在Visual C#项目选择ASP.NET WEB应用程序,确定后生成WebApp1项目,在项目中添加对Grove.dll的引用,Grove.dll位于GroveKit的安装路径下,您也可以通过.NET Configuration将Grove添加到程序集缓存中。

2.

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

art\grove_003.jpg

图3 设置数据库连接串

3.

配置当前Web项目的web.config(在</configuration>之前加入以下配置)

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

4.

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

art\grove_004.jpg

图4 预览实体映射类

5.

检查当前预览的实体类,点击生成文件按钮,该实体类将被生成到解决方案资源管理器当前选中的路径下。

6.

重复4,5步骤就可以生成其他表的映射实体类。

Customer.cs
using System;
using Grove.ORM;
[DataTable("Customers")]
public class Customer
{
int _CustomerID;
string _CustomerName;
string _CustomerDesc;
int _Status;[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;}
}
[DataField("Status")]
public int Status
{
get{return this._ Status;}
set{this._ Status=value;}
}
}
Address.cs
using System;
using Grove.ORM;
[DataTable("Addresses")]
public class Address
{
int _AddressID;
int _CustomerID;
string _Address;[KeyField("AddressID")]
public int AddressID
{
get{return this._AddressID;}
set{this._AddressID=value;}
}
[ForeignKeyField("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.实体映射类

2.2对象持久化

Grove提供ObjectOperator实现对映射实体对象的数据库持久工作,并通过IObjectQuery接口实现对复杂数据库关系映射实体的查询,主要接口如下:

方法说明

Insert

新增一个对象

Update

根据条件更新一个对象

Remove

根据条件删除一个对象

RemoveChilds

删除所有关系对象

Retrieve

返回一个对象

RetrieveChilds

返回所有关系对象

GetDataReader

返回IDataReader

GetObjectSet

返回对象集合

GetObjectSource

根据对象定义返回DataSet

GetCount

从数据源返回记录条数

BeginTranscation

在数据库支持事务的基础上,开始事务处理

Commit

完成当前事务

Rollback

回退当前事务

2.3数据查询

如一般的关系型数据库所具有的查询功能一样,Grove也有着非常丰富的查询功能,如对象查询、函数查询、子查询、排序查询等。这里对对象查询做简单介绍,其它查询读者可以自行参考Grove的开发文档。Grove提供ObjectQuery 帮助ObjectOperator从数据源查询数据, ObjectOperator 需要通过ObjectQuery解析实体对象中的属性(System.Arrtibute)定义,并构造查询语句。ObjectQuery在运行时往往需要定义筛选语句(请参考筛选语句的语法定义)。例如,检索Customer对象,当State 属性等于WA的情况:

ObjectQuery query=new ObjectQuery(typeof(Customer),"this.State='WA'");

当检索需要返回所有对象时,则不需要定义筛选语句

ObjectQuery query=new ObjectQuery(typeof(Customer),"");

2.4筛选语句的语法定义

在ObjectQuery中使用的筛选允许你在定义的时候,根据使用面向对象语法规则进行定义筛选语句。

操作描述

!, not

用于比较布尔型,例如:

!Order.CustomerID.Contains(Customer.CustomerID)

<, >, <= , >=

用于值比较,例如:

Order.Quantity >= 12

=, !=, <>, = =

用于值判断,例如:

Customer.Country = 'USA' and Customer.Region != 'WA'

and, &&

用于逻辑判断,例如:

Customer.Country = 'USA' and Customer.Region = 'WA'

or, ||

用于逻辑判断,例如:

Customer.LastName = 'Smith' or Customer.LastName = 'Jones'

 

三、总结

以上就是ORM的简单实现,复杂的关系对象映射及关系映射实体的查询也是ORM中尤为重要的一块处理,为了屏蔽各数据库之间的SQL差异,很多好的ORM框架都提供一种符合面向对象语言本身语法规则的Query Language支持,例如实现对数据库函数的支持时,会通过定义一些公开的,与编程语言接近的语言来实现,比如说定义Object.Size(),Object.Sum()等类方法式操作语法,在逻辑判断的时候提供一些语言本身的逻辑运算符支持,比如c#中的&&表示and,||表示or等等这些一系列的面向对象编程风格的支持,都很好地为基于关系型数据库支持的系统开发向“面向对象”提供了有力的支持。Grove目前对关系对象查询有很好的支持,感兴趣可以到Grove的网站了解详细信息。

注:关于Grove的详细信息和安装包,支持站点已经提供了一些相关帮助和下载。http://grove.91link.com

转载于:https://www.cnblogs.com/ipointer/archive/2005/07/27/201242.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/277306.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

[book]道法自然

前不久读了王咏刚的〈凌波微步〉和〈凌波微步II〉&#xff0c;感觉不错。今天把他老人家的《道法自然》也买了下来。在dearbook看到关于这本书的长篇大评&#xff0c;也一块copy了下来&#xff1a;http://www.dearbook.com.cn/book/viewbook.aspx?pnoTS0023954认真的作者&…

列表嵌套字典,根据字典某一key排序

在返回列表嵌套字典时候&#xff0c;往往需要对数据进行一定的处理&#xff1a;按照字典中某一个key排序 In [87]: a [{"name": "牛郎", "age": 23},{"name":"许仙", "age": 20},{"name":"董永&q…

写出C语言中5种数据类型的名称及其关键字,求C语言中的32个关键字及其意思?...

关键字如下&#xff1a;一、数据类型关键字(12个)&#xff1a;(1) char &#xff1a;声明字符型变量或函数(2) double &#xff1a;声明双精度变量或函数(3) enum &#xff1a;声明枚举类型(4) float&#xff1a;声明浮点型变量或函数(5) int&#xff1a; 声明整型变量或函数(6…

想要设计自己的微服务?看这篇文章就对了

欢迎大家前往腾讯云社区&#xff0c;获取更多腾讯海量技术实践干货哦~ 本文由我就静静地看 发表于云社区专栏 本文通过使用Spring Boot&#xff0c;Spring Cloud和Docker构建的概念验证应用程序的示例&#xff0c;为了解常见的微服务架构模式提供了一个起点。 该代码在Github上…

mysql 开发进阶篇系列 41 mysql日志之慢查询日志

一.概述 慢查询日志记录了所有的超过sql语句( 超时参数long_query_time单位 秒&#xff09;&#xff0c;获得表锁定的时间不算作执行时间。慢日志默认写入到参数datadir(数据目录)指定的路径下。默认文件名是[hostname]_slow.log&#xff0c;默认超时是10秒&#xff0c;默认不开…

分数相同名次排名规则C语言,如何给数据排名(相同分数相同名次)-excel篇

使用Rank函数来做数据排名该函数是返回一个数值在一个数字列表中的排名。语法&#xff1a;RANK(number,ref,order)RANK(对象,范围,参数)number(必填参数):是特定单位格中的数据&#xff0c;需要在整个数字列表中排名的单个对象。ref(必填参数):是指需要排名的整体数列。即范围&…

MySql的连接查询

若一个查询同时涉及到两个或者两个以上的表&#xff0c;则称之为连接查询。常见的包括&#xff1a;等值连接查询&#xff0c;自然连接查询&#xff0c;非等值连接查询&#xff0c;自身连接查询&#xff0c;外连接查询&#xff08;左右连接&#xff09;。 1.等值与非等值连接查询…

qt运行C语言后无显示,qt designer启动后不显示界面问题的原因与解决办法-站长资讯中心...

Qt 5.6.1无论是在vs里双击ui文件还是直接启动designer.exe都一直无法显示界面&#xff0c;但任务管理器中可以看到该进程是存在的。前几天还正常的&#xff0c;但昨天加了一块NVIDIA的显卡(机器自带核显)&#xff0c;可能与此有关。幸好还可以通过QtCreator打开ui文件进行编辑。…

OpenSolaris北京用户组的第一次活动

OpenSolaris北京用户组的第一次活动作者: BadcoffeeEmail: blog.olivergmail.comBlog: http://blog.csdn.net/yayong2005年10月10月15号&#xff0c;OpenSolaris北京用户组在北京西郊宾馆会议厅组织了成立以来的第一次活动。尽管OpenSolaris早在2005年6月14日就正式开放源代码&…

Android PermissionUtils:运行时权限工具类及申请权限的正确姿势

Android PermissionUtils&#xff1a;运行时权限工具类及申请权限的正确姿势 ifadai 关注 2017.06.16 16:22* 字数 318 阅读 3637评论 1喜欢 6PermissionUtil 经常写Android运行时权限申请代码&#xff0c;每次都是复制过来之后&#xff0c;改一下权限字符串就用&#xff0c;把…

Linux基础监控小工具nmon

nmon是一种在AIX与各种Linux操作系统上广泛使用的监控与分析工具&#xff0c; nmon所记录的信息是比较全面的&#xff0c;它能在系统运行过程中实时地捕捉系统资源的使用情况&#xff0c;并且能输出结果到文件中。nmon工具可以帮助在一个屏幕上显示所有重要的性能优化信息&…

vue的配置环境篇

1.电脑已经安装的nodejs和webpack。 2.1&#xff09;打开cmd。winr。可以直接输入node -v查看版本。安装淘宝镜像 npm install -g cnpm --registryhttp://registry.npm.taobao.org &#xff0c;安装成功可以查看下&#xff0c;cnpm -v 3.安装vue脚手架&#xff0c;输入命令&am…

Agilent RF fundamentals (4)- Impedance match and distortions

1 Impedance match&#xff1a; 2 distortions&#xff1a; Solar radiation produces background noise 转载于:https://www.cnblogs.com/huangbaobaoi/p/9650937.html

android论坛功能开发教程,Android教程 如何免费生成论坛App

介绍按照快速集成文档&#xff0c;您可以很容易的把BBSSDK提供的功能集成到您的应用中&#xff0c;然后使用BBSSDK来做开发。在集成前&#xff0c;您也可以先下载示例Sample的源码工程(包含应用内打开pdfoffice等格式文件)。使用Android Studio打开后&#xff0c;编译出网站上提…

自动化测试===adb 解锁手机的思路

在adb里有模拟按键/输入的命令 比如使用 adb shell input keyevent <keycode> 命令&#xff0c;不同的 keycode 能实现不同的功能&#xff0c;完整的 keycode 列表详见 KeyEvent&#xff0c;摘引部分我觉得有意思的如下&#xff1a; keycode含义3HOME 键4返回键5打开拨号…

android 编译器有问题,Android Studio 3.0 Beta 2发布:解决编译器bug

5月18日&#xff0c;IT之家曾经报道&#xff0c;谷歌发布了Android Studio 3.0的测试版&#xff0c;新增了对Kotlin语言的支持&#xff0c;而日前&#xff0c;谷歌发布了Android Studio 3.0的Beta 2版本。此版本并无新功能加入&#xff0c;不过修复了一个困扰开发人员的bug&…

Kali安装magescan评估工具

Magento &#xff08;麦进斗&#xff09; 是一套专业开源的电子商务系统。Magento设计得非常灵活&#xff0c;具有模块化架构体系和丰富的功能。易于与第三方应用系统无缝集成。其面向企业级应用&#xff0c;可处理各方面的需求&#xff0c;以及建设一个多种用途和适用面的电子…

领域驱动设计在马蜂窝优惠中心重构中的实践

前言 正如领域驱动设计之父 Eric Evans 所著一书的书名所述&#xff0c;领域驱动设计&#xff08;Domain Driven Design&#xff09;是一种软件核心复杂性应对之道。 在我们解决现实业务问题时&#xff0c;会面对非常复杂的业务逻辑。即使是同一个事物&#xff0c;在多个子业务…

鸿蒙系统发布会是什么时候,鸿蒙系统2.0发布时间是什么时候?或将与EMUI11一同发布!...

对于鸿蒙系统OS一直以来就备受大家的关注&#xff0c;作为华为自主研发的操作系统&#xff0c;它是华为之光&#xff01;很多人翘首盼望着它的到来&#xff0c;自1.0版本后鸿蒙系统2.0发布时间似乎确定下来了&#xff01;届时会与EMUI11一同向大家介绍&#xff01;今日&#xf…

HZNU 2019 Summer training 8

A - Petya and Origami CodeForces - 1080A 题意&#xff1a;制造一份邀请函需要2份a物品&#xff0c;5份b物品&#xff0c;8份c物品&#xff0c;一个盒子里面有k份物品&#xff08;可以为a或b或c&#xff09;问你制造n份邀请函需要用多少个盒子 题解&#xff1a;加起来就行了…