NDO中的ActiveRecord 简介
我开发的这个ActiveRecord 思想来源于现在非常火爆的Rails框架中的ActiveRecord - 活动记录,该模式来源于国际软件大师Martin Flowler所著的<<企业应用架构模式>>。文中Martin Flowler下了定义:一个对象,它包装数据库表或视图中的某一行,封装数据库访问,并在这些数据上增加了领域逻辑。 意思是说活动记录是一个实体对象,该实体对象代表数据库表或视图中的一行,并在该实体对象中封装了数据访问逻辑和业务逻辑代码,对象既有数据又有行为。该对象到底是数据对象?DAO对象?BIZ 对象呢? 马丁福莱道:领域模型,即BIZ对象(较业务对象)。ActiveRecord应用最广的是Ruby 中的Rails框架,并且把ActiveRecord的感念又大大延伸了.Rails框架中的ActiveRecord完全可以和JAVA中的hibernate 相比美,该框架中的"简单就是美","约定胜于配置"等敏捷思想深深的影响了我,使我产生开发NQL的一个动力.Rails中的活动记录支持一对多,多队一,多对多等对象关系映射模式.我做的ActiveRecord目前支持单表映射,对于一对多,多队一,多对多等映射模式以查询对象来代替.对于为什么要这样呢?"简单就是美",如果你把映射做的太多,太复杂,那学习成本就很高,于是我避开这一环节做了一个NQL强大的查询组件来做为ActiveRecord的助手,使ActiveRecord的概念仍停留在Martin Flowler的定义之中,没有达到完全的ORM目的。林学鹏开发的Grove rm 的思想和我的差不多,只做单表或视图的映射再配合上Oql语言,这在当时是非常火的,因为.NET 平台的一个优点就是短,平,快,果你做的太复杂反而用的就少,比如NHibernate,和Castle框架中的活动记录。至于将来是否支持一对多,多队一,多对多等映射模式,那时后话,有可能会支持的.。
ORM 性能比较(除了数据缓冲机制)
1. 映射比较
OR映射在hibernate和NHibernate中用xml做为映射的,映射的开销是输入输出操作以及DOM对象的解析
Grove的单表映射和Castle中的活动记录是用标签做映射,映射的开销是通过反射读取标签信息来得到映射信息
NDO 的ActiverRocord 或NQL通过直接读取数据库表的元数据做映射,映射开销是读数据库得到元数据。(注:这种方式说白了根本不叫映射,具体原因后面或做介绍)
通过读取元数据来看NDO 的ActiverRocord 或NQL的映射开销比较大。
2.对象的加载以及sql的动态生成
当今流行的ORM框架,无论是以xml配置做映射还是标签做映射都需要通过反射来加载对象的数据,通过反射来动态生成sql.。
在这方面ActionPack 框架,Ruby on rails 或许我对rails理解有误)方面做的比较好,NDO 的ActiverRocord 就吸收了这两者的思
想,无论在数据的加载或sql的动态生成方面就没有任何反射开销,性能就相应的高了很多!
例子:下面的例子都是以Sql Server2000中的默认数据库Northwind为例
NDO中的活动记录支持三种类型,一种是弱类型,另外一种是强类型,第三种是强类型和弱类型之间,只有强类型的活动记录才能够完全支持从数据库中得到实体对象的IList集合,其它两种只支持返回DataTable,DataSet,DataReader等结果集对象
1。弱类型的例子:
1.1数据加载Load ,或LoadByKey返回数据库中的一条记录,如果有多条只加载第一条记录
product.LoadByKey(1);
this.Text = (string)product["ProductName"] + "--------" + product["SupplierID"];
SQL 输出
[ProductID],
[ProductName],
[SupplierID],
[CategoryID],
[QuantityPerUnit],
[UnitPrice],
[UnitsInStock],
[UnitsOnOrder],
[ReorderLevel],
[Discontinued]
FROM
[Products]
WHERE
[ProductID] = @ProductID
1.1数据加载 2
product.ID = 1;
product.Load();
this.Text = (string)product["ProductName"] + "--------" + product["SupplierID"];
SQL 输出同上
1.1 数据加载3 返回了多条记录但是只加载了一条
product.SetValue("SupplierID",7);
product.Load();
this.Text = (string)product["ProductName"] + "--------" + product["SupplierID"];
SQL 输出
[ProductID],
[ProductName],
[SupplierID],
[CategoryID],
[QuantityPerUnit],
[UnitPrice],
[UnitsInStock],
[UnitsOnOrder],
[ReorderLevel],
[Discontinued]
FROM
[Products]
WHERE
[SupplierID]=@SupplierID
1.2 数据查询(返回零条或多条记录,这个类似与Quey对象的用法,活动记录里面封装了CRUD的四个查询对象方便用户更灵活的操作数据库)
this.dataGrid1.DataSource = product
.SelectCommand
.NewWhere("SupplierID",7)
.And("CategoryID",3)
.GetDataTable();
SQL 输出
[ProductID],
[ProductName],
[SupplierID],
[CategoryID],
[QuantityPerUnit],
[UnitPrice],
[UnitsInStock],
[UnitsOnOrder],
[ReorderLevel],
[Discontinued]
FROM
[Products]
WHERE
[SupplierID] = @SupplierID
AND [CategoryID] = @CategoryID
1.3 数据插入操作
rg.ID = 6;
rg["RegionDescription"] = "66";
SQL 输出
[RegionID],
[RegionDescription]
) VALUES (
@RegionID,
@RegionDescription
)
1.4数据更新
rg.ID = 6;
rg["RegionDescription"] = "66666";
SQL 输出
[RegionID],
[RegionDescription]
FROM
[Region]
WHERE
[RegionID]=@RegionID
UPDATE [Region] SET
[RegionDescription] = @RegionDescription
WHERE
RegionID = @RegionID
1.5 数据删除
rg.ID=6;
rg.Delete();
SQL 输出
WHERE
RegionID = @RegionID
1.5 数据删除2(条件删除(活动记录里面封装了Table数据库表的元数据对象里面),也可以以Filter方式进行删除或Where子句的方式进行删除)
con.Execute();
SQL 输出同上