|
基于 dot Net 的通用快速软件开发框架(NGSDF)
在 dot Net应用开发中,如何利用对象的概念,方便、快速、灵活地创建稳定的软件系统,是许多软件开发公司的目标,本文基于一个通用的
dot Net开发框架——Class Engine,简要阐述对象技术的使用,以及Class如何与界面结合,组成整个软件开发流程,下面简称此框架为NGSDF
1、 前言
2、 Class Engine的体系结构
3、 Class Engine 的特性
4、 Class Engine 的使用
5、 O/R 映射定义
6、 Class Engine 在ASP.Net开发中的应用
7、 由NGSDF实现零代码开发
8、 NGSDF提供的其他功能
9、 总结
一、前言
随着 dot Net 技术的推广,越来越多的公司正在向 dot Net 转型,采用 dot Net 开发系统,但是如何方便、快速、灵活地创建稳定的软件系统,是许多软件开发公司追求的目标。为实现这个梦想,通用的
dot Net开发框架——Class Engine孕育而生。设计人员可以专注于部件的功能设计,也就是Class的定义 。
二、Class Engine 的体系结构
Class Engine 被设计成由客户端来管理对象状态,持久化管理器(DataObjectManager,负责持久化对象获取、创建、更新、删除)不管理持久化对象的状态,也就是说不存在一个"容器"来保存所有管理器创建的对象,而是根据客户端的请求进行对象的获取、创建、更新、删除等操作。这使得开发者只需要定义一个可序列化的实体对象,即可实现分布式应用的对象持久化。
Class
Engine考虑在Microsoft Windows平台下分布式应用存在不同的应用模式,典型的如Entity-Collection-Class模式(简称为ECC模式),这些构架模式代表了整个应用的结构,它根据不同的应用特征变化。Class
Engine不期望提供一个通用的分布式应用的构架模式,而是允许在Class Engine持久化框架的核心服务上扩展不同的应用模式来满足系统的要求。

三、Class Engine 的特性
1、支持的数据源
Class Engine仅支持数据源为关系型数据库的对象持久化,目标数据库需要提供相应的Microsoft .Net Data
Provider引擎,支持的数据库包括Oracle, Sybase, SQLServer, DB2, Access, Dabase,
Foxpro, VFP
2、映射定义
Class Engine目前支持的映射配置
· 代码文档属性元数据定义。利用映射属性类在持久化类或类的属性定义。
3、事务支持
Class Engine本身并不管理事务,但当在事务环境中时,支持事务的完成标志(Complete)和异常时取消(Abort)。
4、其他特性
· 基于客户/服务器模式的框架。
· 自动属性类型匹配。对象属性与字段映射时不需要定义数据类型,简化了映射的定义。
· 支持持久化对象的关联。允许建立不同持久化对象之间的关联,定义关联多重性(一对一、一对多)。
· 事务支持。Class Engine本身并不管理事务,但提供对事务的控制(同意或取消事务)。
当前Class Engine还不支持"懒装载"(Lazy Loading)或"按需装载"(On-Demand
Loading)。
四、Class Engine 使用
1、定义一个持久化类
持久化类实际上是一个定义了属性(Property)或字段(Field)的类,因此持久化类的定义非常简单,但持久化类不能是抽象类并且需要有一个无参数的public的构造化函数。
字段或属性只有被定义为持久化属性时才会进行持久化,持久化属性的数据类型必须定义为:
· .Net框架的基本类型
· Byte数组(二进制数据)
· 实现System.Collections.IList的类
· 其它持久化类(对象关联时)
下面是一个简单的持久化类"Customer"的定义:
[C#]
public class Customer
{
//必须定义无参数的构造函数
public Customer()
{
}
public string Id { get; set; }
public string Name {get; set; }
public string Phone {get; set; }
}
持久化类的映射配置可以使用属性在类上定义。类映射必须定义至少一个主键。有关对象映射配置的定义参见O/R映射定义
Customer类的采用属性进行映射配置的定义如下:
[C#]
[ObjectMapping("customer","customer")] //定义映射的表名
public class Customer
{
//必须定义无参数的构造函数
public Customer()
{
}
[PropertyMapping("id",true)] //定义对象属性映射的数据库字段,true表示本属性为主键
public string Id { get; set; }
[PropertyMapping("name")]
public string Name {get; set; }
[PropertyMapping("phone")]
public string Phone {get; set; }
}
Class Engine并不定义属性映射的字段类型,Class Engine采用自动匹配的方式进行处理。.
2、管理持久化对象
持久化对象通过数据对象管理器(DataObjectManager)来进行访问。DataObjectManager提供了对象的获取、新增、更新和删除接口。
新增持久化对象实例
新增对象到持久存储中,首先必须创建一个新持久化对象实例,然后利用DataObjectManager接口将新对象保存到持久存储中
下面的示例简单演示了一个创建新Customer对象到持久存储中:
[C#]
Customer customer = new Customer(); //创建持久化对象实例
customer.Id = "0001"; //设置对象属性
customer.Name = "john";
customer.Phone = "555-55555";
customer.Complete(); //保存到持久化存储中
获取持久化对象实例
持久化对象实例必须通过对象的主键获取,如果主键只有一个属性,则可以直接利用属性定义的类型的对象;如果主键有多个属性,则需要定义一个主键对象来访问。
下面的示例简单演示了存在在持久存储中的Customer实例,因为Customer的主键只定义个一个属性:Id属性,因此可以直接用Id值获取对象实例:
[C#]
//因为同一个DataObjectManager可以为多个持久化类服务,因此需要指定要返回的对象类型,这里通过typeof(Customer)获得。
Customer customer = (Customer) DataObjectManager.Instance.GetObject(typeof(Customer),"0001");
更新持久化对象实例
当一个持久化对象被修改后需要更新,已保存这种修改。
下面的示例演示了保存修改后的Customer实例:
[C#]
//首先获得对象实例。这步不是必需的,也可以用new的方式创建新对象,但这个对象必须存在,否则将出错。
Customer customer = (Customer) DataObjectManager.Instance.GetObject(typeof(Customer),"0001");
customer.Name = "Will Smith"; //修改Name属性
customer.Complete(); //保存修改
删除持久化对象
删除存在于持久化存储中的对象实例
下面的示例演示了删除Customer实例:
[C#]
//首先获得对象实例。这步不是必需的,也可以用new的方式创建新对象,但这个对象必须存在,否则将出错。
Customer customer = (Customer) DataObjectManager.Instance.GetObject(typeof(Customer),"0001");
customer.Complete(); //删除对象
3、定义关联关系类
对象系统中,各个实体对象之间常常存在关系,它们需要相互协作,持久化类之间可以建立关联,用于定义父类与子类的关系称之为关联关系,用于代表子对象的类属性称为关联属性。关联关系必须在父类定义(RelationKeyMapping).
4、使用持久化控制接口
持久化管理器DataObjectManager支持IPersistenceControllable接口,实现IPersistentControllable接口持久化对象会被DataObjectManager的持久化操作回调,以提供持久化对象对持久化操作的控制。
IPersistenceControllable接口定义控制持久化操作新增、更新、删除、获取的接口。
下面的例子演示实现IPersistenceControllable接口的Student类利用BeforeNew接口在新增前检查是否有null值,并将null值设置为缺省置,以避免写入数据库时产生异常(表的字段被定义为不允许为空):
[C#]
//学生类定义
[ObjectMapping("student")]
public class Student:IPersistenceControllable
{
[PropertyMapping("student_id",true)]
public int StudentId { get; set; }
[PropertyMapping("name")]
public string Name;
[PropertyMapping("homeplace")]
public string HomePlace; //学生的出生地,映射表不允许为空
//实现IPersistenceControllable接口
public void BeforeNew(){
//在新增对象到持久化存储前检出对象数据的有效性
if (Name == null || Name.Trim()=="")
throw new ArgumentNullException("Name不允许为空");
if (HomePlace == null) HomePlace = "";
}
public void AfterNew(){};
public void AfterLoad(){};
public void BeforeUpdate(){};
public void AfterUpdate(){};
public void BeforeDelete(){};
public void AfterDelete(){};
}
//下面的代码演示新增了实现IPersistentControllable接口的持久化对象
//首先创建一个新的学生
Student student = new Student();
student.Id = 2;
//未设置Name属性
//student.Name = "Mark";
//下面的代码出现异常,因为未设置Name属性
dom.NewObject(student);
//下面的代码将不会出现异常,因为HomePlace在BeforeNew方法中设置了缺省值
student.Name = "Mark";
student.Complete();
IPersistentControllable在事务环境中因为事务可能被回滚,但对IPersistentControllable的调用不能回滚,因此不能在事务环境中使用IPersistentControllable接口来处理对持久化成功依赖的要求。
5、O/R映射定义
定义类映射
持久化类需要定义保存数据的表。对象映射定义映射的表名,属性与表字段的映射参见定义属性映射。
属性定义
ObjectMappingAttribute用于定义对象映射的表名,属性只能定义在类上。
下面例子演示了持久化类定义ObjectMapping属性:
[C#]
[ObjectMapping("customer")] //Customer映射数据库的表"customer"
public class Customer
{
//...
}
持久化类也可定义数据源属性(DataSourceAttribute),该数据源仅用于该类,如下:
[C#]
[ObjectMapping("customer")] //Customer映射数据库的表"customer"
[DataSource("accessdb","OleDb",@"Provider=Microsoft.Jet.OLEDB.4.0;Data
Source=test.mdb")] //定义用于Customer类的数据源
public class Customer
{
//...
}
定义属性映射
持久化类通过属性映射定义类属性与表字段的映射。Class Engine并不要求定义属性的数据类型,持久化处理器自动进行数据类型的匹配。
属性定义
属性映射使用PropertyMappingAttribute进行设置,PropertyMappingAttribute只能定义在类的Field和Property上。
PropertyMappingAttribute可以设置以下属性:
属性 类型 描述
Field System.String(.Net框架类型),string(c#) 映射表的字段名
IsPrimaryKey System.Boolean(.Net框架类型),bool(c#) 是否主键。true表示该属性是主键属性
IsIdentity System.Boolean(.Net框架类型),bool(c#) 是否自动赋值字段。某些数据库支持自动增长字段类型,在新增记录是不需要提供该字段的值,而由数据库自动设置。
DefaultValue Sysem.Object(.Net框架类型), object(c#) 缺省值
下面的例子演示属性的映射定义:
[C#]
[ObjectMapping("customer")]
public class Customer
{
[PropertyMapping("id",true)] //映射表字段id,并且是对象主键
public string CustomerId;
[PropertyMapping("name")] //映射字段name
public string Name;
//映射字段valid,并且需要数字化布尔值的转换
[PropertyMapping("valid",DataTransform = DataTransformFormat.NumbericBoolean)]
public bool Valid;
}
定义关联
关联定义持久化对象之间的关系,在Pdo中关联由父端和子端组成,父端和子端均可以定义关联对方的属性,可以通过关联属性来访问关联的对象。
定义父类和子类之间的关联,需要定义关联关系,关联键、和在持久化类的关联属性。
关联关系定义
关联定义持久化类与持久化类的关系,关系的定义端为父类,父类连接子类,子类也可以连接父类。持久化管理器在装载父类时将自动装载关联子类对象,但装载子类时则不会装载父类,则主要是为了避免循环装载。
关联关系定义包括关系的名称和父类、子类以及关联的键定义、关联表等关联信息。
RelationKeyMappingAttribute定义关联关系,一般定义在父类上,可以设置以下属性:
属性 类型 描述
childType System. Type (.Net框架类型) 子类型。
primaryKey System.String(.Net框架类型),string(c#) 父类主关键字。
relationKey System.String(.Net框架类型),string(c#) 子类主关键字。
cascadeDelete System.Boolean(.Net框架类型),bool(c#) 是否允许级联删除,即删除父对象时同时删除子对象。可选,默认为false。
实体对象的状态管理
Class Engine库在进行持久化实体对象的管理操作时,依赖于对象的状态。为了管理对象的状态,实体类需要实现IPeristentObject接口,IPeristentObject提供了查询状态、设置状态的接口。
对象状态由类ObjectState定义,包括以下几种状态:
· New:对象为新对象(未存在持久存储中)
· Dirty:对象已被修改
· Persisted:对象已持久化,即对象的数据与持久存储一致
· Deleted:对象已被删除
实体对象可以通过State属性获得对象的状态。
除此之外,IPersistentObject还提供了一个用于标记预备删除的属性DeletionMark,当属性为true时表明对象请求从持久化存储中删除。
客户端维护的对象状态
为了支持客户/服务器方式的应用,Pdo持久化管理器并不提供对象的状态管理,在Class Engine库中持久化管理器同样不提供对象的状态的管理,而由客户端负责维护其对象的状态,这意味着客户端调用管理器的Save接口后,客户端的实体类的状态并不会变为"Persisted",客户端必须通过调用IPersistent的Complete接口来同步状态。
设计支持对象状态管理的实体类
对象正确的状态变化应当如下:
在一个对象被创建时对象的状态为"New";对象在保存后通过调用Complete接口同步对象的状态,此时对象的状态应当为"Persisted"或"Deleted"(DeletionMark为true);已保存的对象(状态为"Persisted")的持久化属性修改后,其对象状态应当为"Dirty"。
在Class Engine中为了管理实体对象状态,实体类必须实现IPersistObject接口。Class Engine库提供了了实体类基类BasePersistentObject,该类已经实现了IPersistObject接口,因此可以直接从BasePersistentObject继承来产生自己的实体类。
正确地实现对象管理,实体类必须符合以下原则:
· 新建的对象实例,初始状态必须为ObjectState.New(当实体类从PersistentObject继承时,其对象状态将自动为"New")。
· [C#]
· Customer customer = new Customer();
· 修改了对象持久化属性后,应当设置对象为"脏"状态。IPersistentObject的MakeDirty接口设置属性为Dirty,当对象属性修改后应当利用该接口修改对象的状态。
· [C#]
· //下面是Customer类定义,演示如何在对象持久化属性修改后,修改对象状态
· //(持久化类映射定义略)
· public class Customer
· {
· [PropertyMapping("id",true)]
· public string Id;
·
· private string name;
· [PropertyMapping("name")]
· public string Name
· {
· get { return name; }
· set {
· name = value;
· //Name属性修改后,设置对象状态为"脏"
· this.MakeDirty("Name");
· }
· }
· }
持久化管理器处理对象状态的方式
要设置对象的删除标记,只需将DeletionMark设置为true,DeletionMark标记优先于State,Class Engine库的持久化管理器在进行Save操作,遵循以下原则(优先级从上到下):
· 当DeletionMark为true,在执行Save时,如果State为"New",则持久化管理器不作处理,否则将从持久化存储中删除该实体对象。
· 当State为"New",则新增该对象。
· 当State为"Dirty",则更新该对象。
6、视图持久化定义
在Class Engine 中,视图的持久化对象定义和普通表的定义相同,Class Engine支持视图更新
此架构由我公司资深架构师设计,详细使用方法介绍请在“解决方案”栏目下载说明文档。如需试用请在“产品栏目”中下载试用版
|