当前位置:编程学习 > C#/ASP.NET >>

Snake.Net中的ORM(三)

答案:     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中所有的唯一标识都应当是实现IUnique接口的对象,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)查询
  查询是ORM的高级应用也是ORM操作中最难处理的部分。因为查询总是多样化的,如果每个特定查询调用都编制一个对象方法,则维护量太大且扩展性很差,而要编写一个通用的查询接口似乎难度颇大。一些ORM框架会提供一种符合面向对象语言本身语法规则的Query Language支持,但是这种语言本身很累似SQL语法,与标准的SQL语句差别不大,而且这种做法几乎丧失了封装的意义。
  查询的核心问题是Query本身是复杂的、多变的和不可完全预计的,Snake.Net的做法是将其化为一个类。Eastasp.Framework.Data.Query.DataQuery对象就是Snake.Net所提供的查询类,从而实现结构化查询的各种功能。同时通过Eastasp.Framework.Data.DbQueryParser对象可以自动将DataQuery转换成对应的SQL语句。这种的好处是,一方面我们在进行查询操作中就无需关心SQL语句,只需对DataQuery对象进行操作即可,从而实现对查询的封装。另一方面,针对不同公司的数据库产品,我们可以编写特定的DbQueryParser类,以实现对其的支持。
  下面让我们来看一下Snake.Net是如何实现查询功能的:
  
  //declare
  IList customers;
  DataConditionBuilder builder;
  DataSortBuilder builder2;
  IObjectProviderFactory factory;
  
  //query
  builder = DataBindObject.GetConditionBuilder(typeof(Customer));
  builder2 = DataBindObject.GetSortBuilder(typeof(Customer));
  builder.AddCondition("companyname", DataExpressionOperator.BeginsWith, "A");
  builder.AddCondition(DataLogical.Or, "companyname", DataExpressionOperator.BeginsWith, "B");
  builder.AddCondition(DataLogical.Or, "companyname", DataExpressionOperator.BeginsWith, "C"

上一个:ASP.net 验证码(C#)
下一个:Snake.Net中的ORM(二)

CopyRight © 2012 站长网 编程知识问答 www.zzzyk.com All Rights Reserved
部份技术文章来自网络,