系列回顾
本系列前面有三篇文章介绍和演示了AgileEAS.NET平台ORM组件的开发流程及其常见的使用方式,通过前面的三篇文章,大家都可以正常的使用ORM进行正常的开发,本文将提到一个ORM结构性的问题,ORM对象的访问器。
情况说明
提到ORM访问器,我们就不得不提到一个面对对象设计的问题,那就是到底是对象.操作(),还是操作者.操作(对象),对于这样一个有着争论性并且也没有一个明确最优结果的问题,我也不敢在本文中详细的介绍,我将会在合适的时机发布一个讨论:面向对象设计中的对象.操作()还是操作者.操作(对象)。
访问模式变化
AgileEAS.NET平台中的ORM最早是基于对象.操作()的这种思路设计的,在最初的版本中ORM实体对象(IEntity)和表对象(ITable)中包含了ORM的基本操作:读取、更新、删除、插件操作:
我们可以IEntity的定义可以看到,实体记录接口定义了Query、Refresh、Inert、Update、Delete等与数据库同步的操作,也定义了CacheRefresh这样的缓存刷新操作,同样ITable对象也定义了他的操作:
ITable接口定义了Query、Update、Delete等与数据库同步的操作,也定义了CacheQuery这样的缓存查询操作。
在最初的ORM实现中,由ITable和IEntity的实现Table和Entity两个基类中直接实现这些方法,实质上在最高的ORM体系中就不存在ITable和IEntity接口,在那时还没有需要要求基于接口驱动。
至今为止,ORM实体对象(IEntity和ITable)还包含着这一组方法的定义,在漫长的应用开发中prodct.Insert()这样的写法非常的普遍。
在AgileEAS.NET平台ORM的变迁历史中,有两个事情改变了ORM对象及其访问器体系,第一件事是,同一应用要在不同数据库之上运行的需要驱动了基于接口驱动的数据层开发,也就是提出了ITable和IEntity接口,第二件事是SAAS/分布式应用环境催生了ORM访问器的诞生,进而实现了ORM组件定义与操作的分离。
下面我们来看一看ORM访问器的定义IOrmAccessor:
缓存访问器ICacheAccessor:
平台目录在EAS.Data.dll程序中集内置了一个基于数据库连接的ORM访问器(OrmAccessor),他必须基于一个事实存在的数据库连接IConnection和IAccessor访问器,也内置了一个基于内存ORM缓存访问器(CacheAccessor)。
同时,在AgileEAS.NET平台中实现了基于Remoting技术和WebService技术的分布式技术的分布式ORM访问器。
有了ORM访问器,我们在应用开发过程中,就可以使用操作者.操纵(对象)这样的模式进行ORM操作,例如ormAccessor.Insert(product)。
两种模式的集成
AgileEAS.NET平台中的ORM通过ORM访问器提供了操作者.操纵(对象)的这种处理模型,ORM在不同时期实现了这两种不同方法的处理,对于这两种方式,谁也无法说出那个具有决定的优点,一切都是相对的,在操作的方便性上,在面向对象的理论体系上。
AgileEAS.NET平台中的ORM把实体的定义与访问进行了剥离,然后又把ORM对象与访问器进行了一个集成和粘合,即达到如下的结果:
1.ORM即可以通过实体.操作()也可以通过访问器.操纵(实体)完成对ORM实体的操纵。
2.分离ORM实体对象的操作代码,保在ORM实体对象中保留与实体定义相关的代码,实体对象上定义OrmAccessor属性,实现上的操作方法调用Orm访问器的实体操作方法。
3.ORM实体对象与ORM访问器接口偶尔,基于接口驱动,通过代码或者配置,在运行时使用不同的访问器实现。
在实际使用中我发两段等效代码:
/// <summary>
/// 输出全表数据
/// </summary>
public void DemoQuery()
{
ProductList table = new ProductList();
OrmContext.OrmAccessor.Query(table);
int cols = table.Columns.Count;
foreach (Product product in table.Rows)
{
//do
}
}
等同于:
/// <summary>
/// 输出全表数据
/// </summary>
public void DemoQuery()
{
ProductList table = new ProductList();
table.OrmAccessor = OrmContext.OrmAccessor;
table.Query();
int cols = table.Columns.Count;
foreach (Product product in table.Rows)
{
//do
}
}
访问器配置
之前ORM演示的例子我对ORM访问器使用报一个OrmContext进行了声明,在OrmContext类中,对Orm访问器使用直接new的方式进行了实例化:
/// <summary>
/// Orm访问器。
/// </summary>
public static IOrmAccessor OrmAccessor
{
get
{
if (Instance.ormAccessor == null)
{
Instance.ormAccessor = new OrmAccessor();
Instance.ormAccessor.DataAccessor = DataAccessor;
}
return Instance.ormAccessor;
}
}
从代码中我们看到Instance.ormAccessor = new OrmAccessor(),这样一来应用业务与访问器的实现进行了耦合,Instance.ormAccessor.DataAccessor = DataAccessor; 这一句完成ORM访问器所依赖的数据访问器的注入,程序并没有有效的解耦。
解决这个问题的办法,还是老方法,使用AgileEAS.NET平台的控制反转(IOC)组件来完成访问器的解耦,有关AgileEAS.NET平台IOC组件的介绍请参见
AgileEAS.NET平台之对象控制反转一文。
首先我们用以下代码替换OrmContext类:
OrmContext
1 static class OrmContext
2 {
3 /// <summary>
4 /// Orm访问器。
5 /// </summary>
6 public static IOrmAccessor OrmAccessor
7 {
8 get
9 {
10 return ContextHelper.GetContext().Container.GetComponentInstance("OrmAccessor") as IOrmAccessor;
11 }
12 }
13 }
向ClassLib.OrmDemo项目添加一个应用程序配置文件app.config,并写如以下信息:
1 <?xml version="1.0" encoding="utf-8"?>
2 <configuration>
3 <configSections>
4 <section name="EAS.Objects" type="EAS.Objects.ConfigHandler,EAS.IOCContainer"/>
5 </configSections>
6 <EAS.Objects>
7 <object name="DataConnection" assembly="EAS.Data" type="EAS.Data.Access.SqlClientConnection" LifestyleType="Singleton">
8 <property name="ConnectionString" type="string" value="Data Source=vm2003;Initial Catalog=eas;User ID=sa" />
9 </object>
10 <object name="OrmAccessor" assembly="EAS.Data" type="EAS.Data.ORM.OrmAccessor" LifestyleType="Singleton">
11 <property name="DbConnection" type="object" value="DataConnection" />
12 </object>
13 <!--<object name="CacheAccessor" assembly="EAS.Data" type="EAS.Data.ORM.CacheAccessor" LifestyleType="Singleton">
14 </object>-->
15 <object name="DataAccessor" assembly="EAS.Data" type="EAS.Data.Access.SqlClientAccessor" LifestyleType="Singleton">
16 <property name="Connection" type="object" value="DataConnection" />
17 </object>
18 </EAS.Objects>
19 </configuration>
重新编译运行,结束本次演示,在一步篇文章中我将介绍ORM中使用SQL语句实现ORM不能实现的特定业务。
链接
QQ群:116773358
本文转自 agilelab 51CTO博客,原文链接:http://blog.51cto.com/agilelab/603025