听棠.NET

用积极乐观的心态,面对压力
posts - 307, comments - 10812, trackbacks - 112, articles - 5
  博客园 :: 首页 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理

公告

SmartPersistenceLayer 2.0(3)---实体操作篇

Posted on 2004-11-13 23:36 听棠.NET 阅读(...) 评论(...) 编辑 收藏

 

SmartPersistenceLayer 2.0之实体操作篇

       过上一篇的设置篇后,在我们的系统中就可以开始使用SPL的强大功能了,这一节我主要是介绍SPL的实体(Entity)操作。

原理

       SPL中的实体可能与其他PL的实体有所区别,一般如果从理论上讲的话,实体仅仅是数据的属性描述,不应该带有操作方法,这种方式也存在一种缺点,就是实体没有了操作,只能借助辅助类进行实体的操作,而这种操作势必不能是强类型的,而且开发员可能无法彻底站在面向对象的角度开发系统,因此,SPL中采用了实体中集成部分常用操作,即Insert,Update,Delete,Retrieve操作,这样当我们要对实体进行操作时,可以直接调用实体的这些方法,实现强类型的操作控制。

       为了让SPL能自动实现这种功能,实体(Entity)要继承SPL中的EntityObject抽象类,如:

       Public class StudentEntity : EntityObject

这样,这个实体就自动具有了Save(),Retreve(),Delete()的功能。

 

实体操作

       实体的常用操作为新增(Insert)、更新(Update)、删除(Delete) 、获取(Retrieve),在SPL中体现为Save(),Delete(),Retrieve()这三个方法,Save()会自动判断实体是否已经持久化(IsPersistence)来进行InsertUpdate区分。

       下面我还是以上一篇基础设置篇中的例子来演示:

       实体的XML定义如下:

       <class name="StudentEntity" table="Student" database="MyDB">

          <attribute name="Id" column="Id" type="Integer" increment="true" key="primary" />

          <attribute name="No" column="No" type="String" key="primary" />

          <attribute name="Name" column= StudentEntity "Name" type="String" />

          <attribute name="Birthday" column="Birthday" type="Date" />

         <attribute name="Grade" column="Grade" type="Integer" />

          <attribute name="Score" column="Score" type="Decimal" />

</class>

 

实体类如下:内容略,请参照基础设置篇

namespace BusinessEntity

{

    using System;

    using System.Collections;

    using System.Data;

    using PersistenceLayer;

   

    public class StudentEntity : EntityObject

{

     //常量定义部分

        //局部变量定义部分

        //属性定义部分

     }

}

实体新增:

以往的编程模式中,要往数据库的某表中插入一条记录,有人采用SQL语句执行,这要注意SQL语句的正确性,单引号问题(要使用string.replace(“’”,”’’”)进行替换);还有可以采用CommandParameter的方式,这样就可以避免单引号问题;还有人为了提高性能会采用存储过程,那么这些过程都会影响开发的速度,在SPL中我们的过程变的相当简单了:

StudentEntity student=new StudentEntity();  //实体化一个学生对象

//以下进行属性赋值

//student.Id=1;                        //此为自动增长,SPL会自动获取

student.No=200401;

student.Name=张三;

student.Birthday=DateTime.Parse(1979-01-22);

student.Grade=2;

student.Score=580;

try

{    student.Save();          //实体保存

}catch(PlException exp)        //抛出异常

{

     if(exp.ErrorType==ErrorTypes.NotUnique)    //如果是主键冲突

     {

         Response.Write(主键冲突);

}else

     throw exp;

}

步骤分析:

1.       直接New一个实体对象,给对象属性赋值

2.       然后Save(),如果发生主键冲突,则可以通过catch PersistenLayer.PlException异常来处理,判断是否为PersistenceLayer.ErrorTypes.NotUnique,这样就可以完成新增记录。

自动增长:如上面的Id是自动增长列,所以在赋值时不需要赋值,在进行Save()后,自动生成的主键值会自动赋给实体StudentId属性,这样马上可以使用此生成值。

 

实体获取:

       数据插入后,我们会进行更新,删除等操作,当然,在进行这些操作前,我们肯定会很找到这条记录,那先介绍获取Retrieve()

       在我的设计理念中,每个表都会设置一个主键,这会方便查询,SPL中也实出主键功能,实体的Retrieve()就是根据实体的主键,去获取唯一的一条记录,结果要么是一条,要是就是没有。举例 我们要获取学生ID=5的记录:

StudentEntity student=new StudentEntity();  //实例化

student.Id=5;                    //给主键赋值

student.Retrieve();               //进行Retrieve()操作

if(student.IsPersistence)           //如果获取到

{

       //给界面上的控件进行赋值

       txtName.Text=student.Name; 

       ……

}

步骤分析:

1.              给主键赋值,例子中是单主键,当然我是一直提供单主键的,不过,SPL也是支持多主键的,只要在XML文件中定义为primary=true的例,那么在进行Retrieve()之前就要进行先赋值。

2.              进行Retrieve()操作,这个操作就是从XML文件中读取为主键的字段值,然后从数据库中读取,如果存在,则把值都赋给实体属性;如果不存在,则不进行操作

3.              对实体进行IsPersistence判断,如果获取到,此值为true,如果未获取到为false,因此可以根据此值进行不同的处理。

因此在获取后要使用值时,一定要进行IsPersistence的判断,这是比较好的编程习惯哦。

 

实体更新:

当我们获取实体后并赋值给界面上的控件后,在客户进行修改后就要进行更新操作。

StudentEntity student=new StudentEntity();       //实例化

student.Id=5;                                    //赋主键值

student.Retrieve();                              //获取实体

if(student.IsPersistence)                       //如果存在

{

         student.Name=txtName.Text;           //获取新值

         …….

         try

         {

              student.Save()              //进行更新

}cartch(PlException exp)                 //捕捉异常

{

     if(exp.ErrorType==ErrorTypes.RestrictError) //如果是级联更新异常

     {

         Response.Write(有级联更新约束错误);Response.End(); //友好提示

}else

{

     throw exp;

}

}

}

步骤分析:

1.       先根据主键值获取实体,我是非常建议这样做的,因为系统是多人进行操作的,在每次更新前先从数据库获取一下,这样可以避免实体被删除的并发性错误,当然如果要彻底避免这种并发性,我们可以设定时间戳字段,在获取后进行时间戳比较即可,关于时间戳在SPL中的实现我将在以后的文章中讲述。

2.       使用Save()方法进行更新,这与新增时使用同一个方法,这是因为Save()的方法会根据实体的IsPersistence值进行不同的操作:如直接New一个实体,进行Save(),默认是新增的,而通过Retrieve()后,此值为true的情况下,会自动以Update操作。这种机制非常好用,因为有时候,我们可以让SPL自己决定操作。我们也可以在更新前不进行Retrieve(),而直接把IsPersistence值赋为true,也可以进行更新操作。

3.       级联异常处理,在进行更新时我们经常会遇到级联约束异常,你可以捕捉到ErrorTypes.RestrictError进行友好信息提示。

 

实体删除:

删除操作跟前面的类似,也是非常简单的。

StudentEntity student=new StudentEntity();

student.Id=5;

student.Retrieve();

if(student.IsPersistence)

{

     try

     {

         student.Delete();

}catch(PlException exp)

{

       if(exp.ErrorType==ErrorTypes.RestrictError) //如果是级联删除异常

     {

         Response.Write(有级联删除约束错误);Response.End(); //友好提示

}else

{

     throw exp;

}

 

}

}

步骤分析:

1.       跟实体更新一样,先要通过主键,获取实体,在进行IsPersistence的判断后再进行删除,这可以删除并发性错误。

2.       在删除时我们可以捕捉级联删除错误异常,进行友好信息的提示。

 

扩展功能

动态赋值

有时候我们会遇到这种情况:实体的字段比较多,有些字段的名称是可以循环的定义的,如12个的金额,可以定义为“Price1Price2…”,象这种为了在赋值与取值时减少输入量,我们通常会采用动态组装属性名,SPL提供了SetAttributeValue(“属性名”,”属性值”)方法来支持这种赋值方式,如:

StudentEntity student=new StudentEntity();

for(int i=1;i<=12;i++)

{

     student. SetAttributeValue(Price+i.ToString(),i.ToString());

}

当然,要注意的就是,不要出现不存在的属性名。

 

多帐套功能

在大型系统中我们会遇到多帐套情况,也就是会存在多个帐套数据库,数据结构完全一致,实体在进行操作时(Save,Delete,Retrieve)时,会动态的从不同数据源中获取,为此实体扩展了多帐套功能。

实体在默认情况是读取XML中配置的数据源的,在操作时我们可以动态指定数据源即可,如:

StudentEntity student=new StudentEntity();

student.DatabaseName=”DB2”;           //动态指定其他的数据源名

student.Id=5;

………….

student.Save();

 

通过指定DatabaseName的值,来动态指定实体要对具体哪个数据源操作。

这里的DB2是个逻辑数据源,关于多帐套的功能介绍将在另一个文章详细描述。

 

内存存储

内丰存储是SPL2.0的新功能,如果要让实体存到内存,减少访问数据库次数,从而提高系统的整体性能,只要在实体的XML配置文件中指明IsSaveToMemory=true即可。

如:

<class name="StudentEntity" table="Student" database="MyDB" IsSaveToMemory="true">

          <attribute name="Id" column="Id" type="Integer" increment="true" key="primary" />

          <attribute name="No" column="No" type="String" key="primary" />

          <attribute name="Name" column= StudentEntity "Name" type="String" />

          <attribute name="Birthday" column="Birthday" type="Date" />

         <attribute name="Grade" column="Grade" type="Integer" />

          <attribute name="Score" column="Score" type="Decimal" />

</class>

在系统开发中,至于实体是从数据库读取,还是从内存读取,这是完全透明的。

关于内存存储的功能,将会在另外的文章中详细描述。

 

总结:

以上介绍好SPL中实体的情况,当然,这仅仅是实体本身的功能,大家可能也想到了“我要根据自定义的查询条件来获取记录呢?”

“我要对表中进行批量更新和批量删除呢?”

这些功能就是SPL中的标准(Criteria)的功能,将会在后续的文章中讲述。

 

 

                                                        听棠

                                200411

MSNtintown_liu@hotmail.com