对象关系映射
AgileEAS.NETORM并没有采用如NHibernate中映射文件的文件的模式,而是采用了直接硬编码的模式实现,ORM体系设计采用了属性/列>数据对象>数据集合(表)的结构:
最基本的思路是一个记录/实体(IEntity)映射一条记录,一个实体包括若干属性/列(Colunm),而一组IEntity和一组Colunm组成一个数据表对象(IEntity),用于对象一个表、视图、或者一个查询结果,下面我涉及到的类、接口介绍一下:
Column
相当于一个数据库表的一个列。组织于数据库与数据库表行中,由1-n个列组成一行数据或一个数据库表,包含了标题、名称、数据类型、数据库列名、大小、值表达式、是否自动增长、值、默认值等属性。这些属性方便用户在定义数据库实体类及表类时使用,在数据库属性类中,常规情况下,一个属性等同于一个数库列,但是,一个属性并不一定关联一个数据库列,也可以关联到一个函数或常量之上。
IEntity
实体接口相关于关系数据库中的一个数据库表行,把一个数据库表行映射库一个数据库记录。
数据库实体接口和数据表接口是ORM中最核心的一个接口,为什么说他是最核心的接口呢,他是ORM映射中的数据实体对象(Object)、他和关系数据库中的关系(表)进行直接的映射、一个数据库表行就是一个只有一个元素的关系(即只有一条记录的表)、数据表是数据库表行的一个纵行扩展。 数据库实体接口中实现了,和数据库表行映射所需求的属性集合,同时也提供了Refresh、Insert、Update、Save、Delete数据库持久化操作和一个CacheRefresh方法。
Refresh方法是数据实体对象从关系数据库表行同步自身的一个方法,他从关系数据库表中取出指定行数据,同步内在中的数据实现对象。
Save方法是数据实体对象根据把自己同步到关系数据库表中的一个方法,当数据库表中存在这条数据行是,修改数据库表中的这一行,如果数据库表行中不存在这一行,则向数据库表中插入这一行。
Insert方法不进行判读直接向数据库插入数据。
Update方法不进行判读直接更新数据库记录。
Delete方法是数据实体对象从关系数据库删除与数据实体对象映射的那一行数据。
CacheRefresh方法同Refresh只是不从数据库而是从缓存。
ITable
数据表相关于关系数据库中的一个数据库表,把一个数据库表映射库一个数据表,ITable中我们定义了Columns列集合、Rows行集合,同时也提供了Query、Save、Delete数据库持久化操作方法和缓存查询CacheQuery。
Query方法是数据表对象从关系数据库表同步自身的一个方法,他从关系数据库表中取出指定行数据,同步内存中的数据表对象。
Query方法在执行过程中,可以一次全部同步数据库表数据,也可以根据条件同步数据库的某一部分数据,在进行条件参数时,需求使用到查询条件对象(Condition)、查询条件单元对象(Element)和结果排序单元对象(OrdeElement)、由这三个对象组合成复杂的查询条件,通过Query方法查询指定条件的数据。
Save方法和Delete方法实现和IEntity定义中的有相似的功能,在此先不作介绍。
CacheQuery实现从缓存同步数据行。
在上面ORM的对象架构中,涉及到两个集合类EntityCollection、ColumnCollection在此文不做特别说明,详细请参考开发包中的类库帮助,下面我说一下ORM中的查询条件。
我们知道在进行数据库操作中要进行条件查询,我们把行、列、表都进行了对象映射,那么SQL条件怎么办,AgileEAS.NET中定义了三个类,查询条件(Condition)、组成条件的元素(Element)、排序条件元素。
Condition
条件类是ORM中的一个功能辅助类,他相当于开发人员在编号SQL语句的过程中所编写的一组查询条件。条件由条件单元组件,如果条件用于查询,在查询时,需要对查询结果排序,刚需求使用排序条件单元,以下是条件类及条件单元的结构关系:
上图为条件、条件单元(Element)、排序单元(OrdeElement)之间的类关系图,条件元素()由方法关联条件单元及排序单元,条件单元(Element)表示的是一个很简单的条件元素,比如 NAME = ‘james’, 排序单元(OrdeElement)也只是表示一个很简单的排序单元,比如:NAME或 NAME DESC,但是在我们进行的企业应用开发中,条件都是很复杂的,比如有这样的条件 NAME = ‘james’ And SEX = ‘男’ And Age < 16,这样的怎么么写,我们使用条件单元组成复杂的条件。这个条件我们使用ORM进行映射:
Condition condition = table.CreateCondition ();
condition.AddElement(new Element(“NAME”,”james”);
condition.AddElement(new Element(“SEX”,”男”);
condition.AddElement(new Element(“Age”,” 16”);
这样就完成了这个条件的定义,在条件的组合及定义条件的过程中,我们就有一个认识,条件并不是光有等值比较,还包括有很多其他的条件类型,同样,条件的组合不光是And 还有Or组合,下图是ORM条件映射中的两个辅助枚举,列举条件类型及条件组合类型。
ElementType
条件类型枚举,定义某个条件的类型,比如=,<,like之类的:
ElementType
在这些定义中,有一个特殊的条件类型,SqlCondition条件类型,我们在进行条件映射时,现实中的数据总是复杂的,有很多无法直接使用各种条件映射出,或者,通过单条件映射组件条件很复杂,我们可以直接使用SQL语句作为条件,在这个时间,就可以使用SqlCondition条件类型。它为我们保留了编写优质高效SQL语名的接口。
ElementCombineType
两个条件或者两条条件元素的组合方式,OR或者AND
////// Condition 类的数据元素(Element)之间的组合方法。 /// public enum ElementCombineType { /// /// And,两个Element 对象之间是以And 为组合条件。 /// And = 0x0000, /// /// Or,两个Element 对象之间是以Or 为组合条件。 /// Or = 0x0001 }
接口驱动的数据层
AgileEAS.NET平台一直在实践着接口驱动的思想,同时也在建议应用开发基于接口驱动,AgileEAS.NET平台实现一组实用并且简单的ORM,应用开发的数据访问层也就是基于ORM技术的数据访问层。
我们在应用开发中,经常会遇到同样的产品需要运行在不同的数据库系统之上,比台有客户需要运行在SQLServer之上的版本、有的需要运行在ORACLR之上的版本。
在这种情况下,采用接口驱动的数据访问层是一个不错的选择;定义一组数据访问层接口组件及其不同数据库类型的的数据访问层实现组件,业务实现依赖于数据接口层而与数据实现层解耦,运行期不同的数据库类型需求只需要修改系统的配置文件。
我来列举一个例子,我做也一个数据访问的例子,我们定义了一个名称为EAS.Exam.DAL.Interface的类库项目,包含了IIteminfo(服务项目)、IIteminfoList(服务项目表)、IProduct(产品)、IProductList(产品表)四个实体接口,一个管理这四个四体类具体实例库的IDALManager接口,由他来完成实体的实例化,下面看定义:
public interface IDALManager
{
IIteminfo CreateIteminfo();
IIteminfoList CreateIteminfoList();
IProduct CreateProduct();
IProductList CreateProductList();
}
同时在EAS.Exam.DAL.Interface项目中我们定义了一个DALHelper的类:
public class DALHelper
{
static string ComponentKey = "EAS.Exam.DAL";
public static IDALManager DALManager
{
get
{
return ContextHelper.GetContext().Container.GetComponentInstance (ComponentKey) as IDALManager;
}
}
}
DALHelper类是一个辅助类,提供了一个DALManager名称的静态属性,返回一个具体实例化的IDALManager对象,可能是SQLServer的实现也有可能是Oracle的实现。
我们在定义一个项目EAS.Exam.DAL.SQLServer分别实现这四个实体接品和DALManager接口:
class DALManager : IDALManager
{
#region IDALManager 成员
public IIteminfo CreateIteminfo()
{
return new Iteminfo();
}
public IIteminfoList CreateIteminfoList()
{
return new IteminfoList();
}
public IProduct CreateProduct()
{
return new Product();
}
public IProductList CreateProductList()
{
return new ProductList();
}
#endregion
}
Oracle数据库的实现EAS.Exam.DAL.SQLServer参考SQLServer的实现。
然后在系统配置文件(IOC)配置部分增加一个名称为EAS.Exam.DAL的对象定义,assembly和type根据需要的数据访问层实现进行配置。
SQLServer数据访问层: