分享
 
 
 

Snake.Net中的ORM(三)

王朝c#·作者佚名  2006-01-31
窄屏简体版  字體: |||超大  

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");

builder.AddCondition(DataLogical.Or, "companyname", DataExpressionOperator.BeginsWith, "K");

builder2.AddSort("companyname", DataSortType.Descending);

customers = factory.GetQueryProvider(typeof(Customer)).Query(builder.ToConditions(), builder2.ToSorts());

for(int i = 0; i < customers.Count; i++){

customer = (Customer)customers[i];

Console.WriteLine("name:{0}", customer.CompanyName);

}

从上面的代码中我们可以看出,Snake.Net执行查询操作时非常简便的。先创建一个条件或排序构造器,然后添加查询的条件或排序的字段;再获取该对象的查询供应者,同时利用条件或排序构造器生成的一组条件或排序字段,进行查询操作;最后按顺序返回符合条件的业务实体的集合。

Snake.Net针对业务实体的查询功能应当是相当先进和完善的。不但支持各种复杂条件的查询和排序,并且还全面支持分页操作。同时还可以通过使用缓存和池,实现对查询的优化处理,大大提高查询的效率。下面我们就来叙述一下缓存和池。

缓存和池是Snake.Net中优化查询的两种主要方式。两者都是通过将业务实体置于内存中,从而提高查询的效率。不同的是在缓存模式下,业务实体对象被加载入内存中,并通过设置过期时限来释放对象。池模式与缓存模式主要区别处在于,池模式有一个存储对象最大数量值,当加载的对象数量超过这个值时,就会抛出PoolOverflowException异常。可见缓存可以将一些内容不经常更新的实体加载到内存中,以提高其访问的速度,但当缓存的对象数量过大时将造成可用内存的紧缺,可以用于少量的不经常变更内容的业务实体的查询;而池模式在一定程度上能够灵活调节其占用内存的大小,从而可以避免在占用的内存过多,反而影响系统的整体性能的情况出现。

Snake.Net提供两种方式使用缓存和池来优化查询。

第一种是手动方式:

//use cache mode

customers = factory.GetQueryProvider(ObjectProviderType.Cache, typeof(Customer)).Query(builder.ToConditions(), builder2.ToSorts());

//use pool mode

customers = factory.GetQueryProvider(ObjectProviderType.Pool, typeof(Customer)).Query(builder.ToConditions(), builder2.ToSorts());

第一种通过配置文件:

<!— use cache setting -->

<section name="eastasp.enterprise.samples.customer">

<key name="query.provider.type">cache</key>

</section>

<!— use pool setting -->

<section name="eastasp.enterprise.samples.customer">

<key name="query.provider.type">pool</key>

</section>

然受使用下列代码,自动调用Cache或Pool模式。

customers = factory.GetQueryProvider(typeof(Customer)).Query(builder.ToConditions(), builder2.ToSorts());

6.自定义的数据访问层(Custom DAL)

在上一节中我们叙述了DataBindObjectDataAccess对象的主要功能,虽然在大多数情况下,DataBindObjectDataAccess对象所实现的数据访问层能够处理所有的操作,但是这种实现也是需要付出一定性能的代价。一方面这种代价带来的是系统开发上的便捷,另一方面这种代价也造成了性能上的下降。因而,Snake.Net希望能够在这种利弊达到一个比较好的平衡,那就是通过开发自定义的数据访问层(DAL)来提升整个系统访问数据库的效率。

所谓自定义的访问层就是在Snake.Net现有框架的基础上,为某一个或几个特殊的实体编写特定的数据访问层,以提高数据库操作的性能。应当说DataBindObjectDataAccess自动生成的SQL语句已经起到了一定的优化作用,但总会产生一定程度上的冗余,以Delete操作为例,Snake.Net在对业务实体进行删除操作时,是根据表的主关键字生成SQL语句的,如果一个业务实体存在子表,将对应子表的每条记录生成一条对应的SQL语句进行删除操作,实际上完全可以根据子表的外关键字或者通过一个和主表关联的执行Delete 操作的SQL进行操作。在自定义的数据访问层中,你完全可以针对某个特定对象、特定数据库编写更优化的SQL语句或存储过程实现对数据库访问性能上的提升。

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有