ORM
ORM,即Object-Relational Mapping(对象关系映射),它的作用是在关系型数据库和业务实体对象之间作一个映射,这样我们在具体的操作业务对象的时候,就不需要再去和复杂的SQL语句打交道,只需简单的操作对象的属性和方法就可以完成对关系数据表的操作。
使用ORM技术数据层完全被隐藏,暴露在程序员面前的只是一些实体类对象,在程序中通过实体类的属性来间接操作数据表中的字段。当然这种操作的转换是由ORM框架来完成的,对于程序员来说,只是简单地做了一些getXXX和setXXX方法就可以完成对关系数据表的操作。程序员不用知道什么时候数据库从Oracle移到DB2,或是移到SQL Server,也不用知道数据库名是什么,甚至表名是什么,字段是什么,对于他来说这没有关系,更甚至于可以不用知道SQL语句,可以不懂数据库的任何知识。只需要在适当的时候,调用实体类的setXXX和getXXX方法,就可以取得和改变数据表字段的值,对于程序员来说,实体类就是存储信息的实体,对实体类的操作,就是对信息实体的操作。如此一来,设计人员只要把系统框架搭出来,把一些实体类交给程序员去实现业务逻辑即可。这样的结构比程序员调用JDBC或者ADO.NET去操作数据库要清晰优雅得多。
数据持久层新的解决方案WebSharp
WebSharp的目标,便是设计一个基于.Net通用的应用软件系统框架,以简化基于.Net平台的企业应用软件的开发。目前,WebSharp关注于企业应用软件的以下几个方面:
1、数据库访问
2、O/R 映射
3、AOP
4、分布式访问
WebSharp主要设计思路及涉及的技术:
在数据库访问部分,使用了ADO.Net和工厂模式;在ORM部分,使用了动态代码生成和即时编译,以及对DataSet进行了扩展;在AOP部分,使用了Proxy机制;在Service Locator部分,使用的主要技术也是动态代码生成和即时编译。
数据实体的表示
应用软件系统,从本质上来说,是计算机对现实世界的模拟。现实世界中的实体对象,在软件系统中,表现为需要处理的数据。在面向对象的系统中,这是通过"类"和"对象"来表示的。参考著名的"MVC"模式,系统中需要处理的数据,在面向对象的系统中,属于实体类部分。
WebSharp在数据的表现上,能够采用两种方式:
第一种方式,充分利用了.Net Framework类库中DataSet的功能,设计了一个EntityData类。这个类继承了DataSet,并增加了一些属性和方法。同数据库的映射关系,采用XML配置文件的方式。XML配置文件可以通过工具来生成。
在实际的应用中,要获取一个User实体对象,可以通过如下方式取得:
EntityData User = EntityProtypeManager.GetEmptyEntity("User");
然后,可以通过如下方式来访问这个对象的属性:
string UserName = User["UserName"]
可以看到,这种方式同纯粹的面向对象的方式有点不同。在这种方式下,数据的表现形式只有一个,那就是EntityData。其好处是明显的,不用为每个实体都单独编写一个类,能够大大减少代码的编写量。其缺点也很明显,那就是不能利用编译器类型检测的功能,如果在调用对象属性的时候,写错了属性的名称,就可能出错,但是这个问题可以通过工具来解决。这种方式,比较符合原来使用ADO编程人员的习惯。
第二种方式,我们可以编写一个User类,然后,按照标准的OO的方法来使用这个类。只不过在编写User类的时候,必须实现PersistenceCapable接口,并且同时可以使用到EntityData类的强大功能。
一个按照这个标准实现的User类的简单示例如下:
Public class User: PersistenceCapable
{
private EntityData user;
public User(bool AutoInit)
{
user = EntityPrototypeManager.GetEmptyEntity("User");
if(AutoInit)
user.NewRecord();
}
public string UserName
{
get{return user.GetString("UserName");}
set{ user["UserName"]=value;}
}
public string UserSex
{
get{return user.GetString("UserSex");}
set{ user["UserSex"]=value;}
}
public string UserBirthday
{
get{return user.GetString("UserBirthday");}
set{user["UserBirthday"]=value;}
}
public int ObjectCount
{
get{return user.EntityCount;}
}
public EntityData EntityData
{
get{return user; }
set{user=value;}
}
public bool Next()
{
return user.Next();
}
public void First()
{
user.First();
}
public void AddNew()
{
user.NewRecord();
}
}
|
可以看出,采用这种方式,User类既可以代表一个单个的User对象,也可以包含一个User对象集合,并且可以通过Next和First方法来遍历。
数据的存取方式
数据存取的目的,是持久化保存对象。在WebSharp中,定义了PersistenceManager接口来实现这个功能。
我们可以使用如下的方式来持久化保存一个对象:
User user= new User(true);
……//处理user
PersistenceManager pm = PersistenceManagerFactory.Instance().CreatePersistenceManager();
pm.PersistNewObject(user);
pm.Close();
|
这样数据就已经保存到数据库中了,代码非常简明和直观,没有一大堆数据库操纵的代码,也不容易发生差错。
事务处理
在很多时候,在处理对象保存的时候,我们需要使用事务处理,特别是在处理一对多结构对象的时候。在WebSharp中,我们可以通过Transaction 接口来完成这个功能。
下面是使用事务处理的一个例子:
User user = new User(true);
……//处理user
PersistenceManager pm = PersistenceManagerFactory.Instance().
CreatePersistenceManager();
Transaction trans=pm.CurrentTransaction;
trans.Begin();
try
{
pm.PersistNewObject(user);
trans.Commit();
}
catch(Excption e)
{
trans.Rollback();
}
finally
{
pm.Close();
}
|
对象的查询
WebSharp提供了对象查询的功能,这个功能通过Query接口提供。可以通过下面的办法来使用Query接口:
PersistenceManager pm = PersistenceManagerFactory.Instance().CreatePersistenceManager(pp);
Query q = pm.NewQuery("User");
q.Filter = "UserName=’zyc’";
q.Open();
EntityData entity = q.QueryData();
dataGrid1.DataSource = entity;
q.Close();
pm.Close();
|
对于执行多表关联的复杂查询情况,WebSharp并没有封装简单数据实体的处理,因为多表关联映射实体类的方法复杂难以控制,WebSharp舍弃了对这种情况的ORM处理,但是WebSharp也提供了直接操纵数据库的数据访问接口——DataAccess,这个接口对ADO.Net进行了一些封装,可以使程序员更加容易的使用ADO.Net的功能,并且能够屏蔽不同数据库之间的差别。
能够通过PersistenceManager的NewDataAccess方法来初始化一个DataAccess对象,然后调用相应的办法来执行需要的功能。
下面是一个简单处理多表关联查询的例子:
PersistenceManager pm = PersistenceManagerFactory.Instance().CreatePersistenceManager();
DataAccess da = DataAccessFactory.CreateDataAccess(ApplicationConfiguration.DefaultPersistenceProperty,pm);
string strSql = null;
strSql = "Select * from Customer a left join CustomerFamliy b on a.CustomerID = b.CustomerID" ;
Websharp.Base.QueryParameterCollection qpc = new Websharp.Base.QueryParameterCollection();
DataSet ds = new DataSet();
da.ExecuteDataset(strSql,qpc,ds,"CUSTOMERINFO");
da.Close();
pm.Close();
his.DataGrid1.DataSource = ds.Tables[0];
this.DataGrid1.DataBind();
|
业务逻辑的处理
有了上面的工作,我们就可以把这些对象组合起来,不再关心数据底层与数据库的操作,而开始专心编写我们的业务逻辑。在面向对象的系统中,业务逻辑表现为对象之间的交互,在一些简单的系统中,没有复杂的业务逻辑,只是一些数据的维护工作,那么,有了上面两个部分的工作,我们实际上可能已经忘成了大部分的工作。在使用WebSharp后,对于业务逻辑的编写,可以变成一个非常自然的过程,也能够节省很多代码量。
最简单的业务逻辑:
private User getUser()
{
User user = new User(true);
user.UserName = “zyc”;
user.UserSex= “男”;
user. UserBirthday = “1980年4月16日”;
return user
}
|
WebSharp应用系统的配置
1、 缓存的配置
WebSharp使用了微软的Cached Application Block来缓存数据,因此,缓存信息必须在应用程序中添加。关于Cached Application Block,可以参见微软的相关文档。
2、 系统持久化配置信息
下面是设置的一个例子:
PersistenceProperty pp=new PersistenceProperty();
pp.ConnectionString="server=192.168.1.205;uid=sa;pwd=;database=HDMS;";//数据库连接字符串
pp.DatabaseType = DatabaseType.MSSQLServer; //数据库类型
pp.MapFileLocation = @"/HDMS/Model/XMLDefinition/"; //XML定义文件的路径
pp.MapFileLocationTye=MapFileLocationType.Assembly; //XML文件路径的类型
pp.UserID="sa"; //数据库用户名,必须与数据库连接字符串中的用户名一致
pp.Password=""; //数据库用户密码,必须与数据库连接字符串中的用户密码一致
ApplicationConfiguration.DefaultPersistenceProperty=pp; //设置应用程序的默认配置属性
|
配置信息的说明如下:
1) 数据库连接字符串、用户名和密码的设置按照常规设置
2) MapFileLocationTye指明XML映射文件的路径类型,可以有三种类型:
a) AbsolutePath:采用绝对路径的形式,在这种情况下,MapFileLocation设置成绝对路径的形式,如:“d:/HDMS/xml/XMLDefinition”。
b) VirtualPath:对于Web应用程序,可以设置为虚拟路径的形式,如“/HDMS/Model/XMLDefinition”。
Assembly:XML文件作为资源文件被编译。采用这种形式,需要将XML文件的生成操作属性设置成“嵌入的资源”,这种情况下,MapFileLocation的格式为:“AssemblyName,NameSpace”。例如,XML文件位于HDMS项目的xml文件夹下面,MapFileLocation可以设置为:“HDMS, HDMS.xml”
小结:
ORM(对象关系映射),是基于数据库应用软件系统的重要组成部分,一个结构良好的ORM框架,可以给软件系统的开发带来很大的好处,因此,在处理这部分内容的时候,需要我们进行精心的设计。WebSharp提供了一个可用的方案,能够方便的简化这方面的开发。