** 5 ** ** .抽象的数据访问层 (Abstract DAL)
**
1) 先说一下几个接口 (interface)
** Eastasp.Enterprise.Objects.IObjectStoreProvider ** 此接口实现对象的 Create, Update 和 Delete 操作。
** Eastasp.Enterprise.Objects.IObjectListProvider ** 此接口实现对象的 Retrieve 操作,在 Snake.Net 中,每个对象都需要一个唯一标识,根据这个唯一标识不但可以获取单个的对象实例,也可以通过 IObjectListProvider 接口获取一组对象集合的实例。
** Eastasp.Enterprise.Objects.IObjectQueryProvider ** 此接口实现对象的查询功能。
** Eastasp.Enterprise.Transactions.ISupportedTransaction ** 此接口实现对象的事物操作。
Snake.Net 提供了一个高度封装的数据访问层类 DataBindObjectDataAccess 。 DataBindObjectDataAccess 实现了上述的所有接口,它是 ORM 中业务实体对象访问数据库的桥梁。虽然,在一般情况下,我们并不需要接触这个类,但是对这个类还是应该简单了解一下,这将有助于对 Snake.Net 更深层次的了解。
DataBindObjectDataAccess 对象是提供了实现了业务实体的的所有数据库访问操作包括创建,更新,删除,获取和查询的能力。
2 ) CRUD 方法 ( 即 Create, Retrieve, Update, Delete 方法 )
曾几何时,程序员每天都将要面对一些简单又繁杂的工作,不停的编写 Insert , Update , Delete 和 Select 之类的 SQL 语句。现在 ORM 把我们从这种简单重复劳动中解放出来。通过 ORM 我们可以不再理会那些陈年的 SQL 语句,只需把精力关注于业务实体的建模中。现在让我们欣赏一下让我们看一下 Snake.Net 是如何实现 CRUD 操作的 , 再以 Customer 实体为例,请看以下代码:
//declare
Customer customer;
IObjectProviderFactory factory;
//Create
customer = new Customer( "AROWT" );
customer . CompanyName = "Eastasp.com" ;
customer . ContactName = "Bruce" ;
customer . ContactTitle = "owner" ;
customer . Address = "Avda. de la Constituci¨®n 2222" ;
customer . City = "Tsawassen" ;
customer . Region = "BC" ;
customer . PostalCode = "S-958 22" ;
customer . Country = " UK " ;
customer . Phone = "0621-08460" ;
customer . Fax = "0621-08924" ;
customer . Save ();
//get provider factory
factory = DataBindObject . ProviderFactory;
try {
//Retrieve
customer = (Customer)factory . GetListProvider( typeof (Customer)) . Get( new StringToken( "AROWT" ));
}
catch (ObjectNotFoundException ex){
Console . Write( "Cann't found object." );
throw ex;
}
//Update
customer . Phone = "0321-02420" ;
customer . Save ();
//Delete
customer . Delete ();
从上面的代码中我们可以发现进行 Create 和 Update 操作时都只需调用 Object. Save () , Snake.Net 将根据 Object 的 State 的状态值,自动判断是创建还是更新操作并执行。而对于 Delete 操作也只需要简单的调用一下 Object. Delete () 方法。一切看起来太不可思议了,但事实的确如此简单。
进行 Retrieve 操作时,我们应当先获取 Customer 实体的 IObjectListProvider 接口,然后根据 Customer 的唯一标识 Unique ,取得 Customer 的实例。我们把上面的代码拆分开来仔细观察下面的代码:
//declare
Unique unique;
Customer customer;
IObjectListProvider provider;
IObjectProviderFactory factory;
//get list provider
factory = DataBindObject . ProviderFactory;
provider = factory . GetListProvider( typeof (Customer));
//create unique
unique = new StringToken( "AROWT" );
//get object
customer = (Customer)provider . Get(unique);
简单点说,要获取一个对象的实例,首先应当根据这个业务实体的类型,获取对应的 ListProvider ;然后,生成对象的唯一标识(在 Snake.Net 中所有的唯一标识都应当是实现 I Unique 接口的对象, Snake.Net 内置定义了 GuidToken 、 StringToken 、 Int64Token 和 Int32Token 分别对应 Guid, string, long, int 类型);最后,根据唯一标识调用 ListProvider 的 Get 方法获取对象实体。
3 )事务处理
目前 Snake.Net 对事物处理,采用了以一种较为简单的方法。
对于一个业务实体类而言,对其 Save 和 Delete 方法的调用,会自动实现对 事务 的支持。确切的说,如果一个业务实体的 Save 或 Delete 操作可能需要对多张表进行多步操作,那么这些操作将被自动包含在一个 事务 内,除非你通过配置文件,禁止使用 事务 。
Snake.Net 可以通过使用 TransactionContext 对象处理一个事务块,包含在该事务块内所有 Object 对象的 Save 和 Delete 操作都将被视为在一个事务内执行。请看下面的代码:
//declare
Customer customer;
Employee employee;
//use transactions
using (TransactionContext context = TransactionContext . Create()){
//create customer
customer = new Customer( "AROWT" );
customer . CompanyName = "Eastasp.com" ;
customer . ContactName = "Bruce" ;
customer . ContactTitle = "owner" ;
customer . Address = "Avda. de la Constituci¨®n 2222" ;
customer . City = "Tsawassen" ;
customer . Region = "BC" ;
customer . PostalCode = "S-958 22" ;
customer . Country = " UK " ;
customer . Phone = "0621-08460" ;
customer . Fax = "0621-08924" ;
customer . Save();
//create employee
employee = new Employee();
employee . LastName = "a" ;
employee . FirstName = "b" ;
employee . Title = "Mr." ;
employee . BirthDate = new DateTime( 1988 , 2 , 2 );
employee . Save();
//must set consistent
context . Consistent = true ;
}
上述代码会将 customer 和 employee 对象各自的 Save 方法 视 为一个事务行为,如果其中任何一个对象保存失败,对会引发事物回滚。特别需要注意的是必须设置 context.Consistent = true; 这行代码,否则事务将不会被执行。当然 TransactionContext 对象也可以使用另一种手动方式执行 ( 调用 TransactionContext 的 Commit 和 Abort 方法 ) 。
4 <span style="FONT-FAMILY: