XCodeFactory2.0完全手册(中)

    在前面的一篇文章中介绍了 XcodeFactory 生成的代码的基本结构和访问类的基本用法,我们是通过类似 IDBAccesser dealTeacher = new TeacherSqlDealer(connStr) ; 来得到访问类实例的,这样做有两个弊端:

(1)         如果我们在某个其它的类中只需要使用一次访问对象,那我们也要new一个出来。这样项目中到处都会看到IDBAccesser dealTeacher = new ***(connStr) ;的身影。而且同一类型的访问类的所有实例都是一摸一样的,所以整个项目中,对于每一个访问类,只要一个实例就可以了。

(2)         IDBAccesser dealTeacher = new TeacherSqlDealer(connStr) ;这样的语句,使我们的项目与具体的数据库类型(例子中是SqlServer数据库)绑定在一起了,如果需要更改数据库类型,我们需要更改所有这样的地方。

 

对于问题(1),大家都知道通过Singleton模式就可以解决问题,问题(2)则可以通过一个工厂来解决。为了使访问类仍然能以基础的方式进行使用,我没有把访问类设计成单件模式,而是通过引入一个静态类DataEntrance来同一管理访问类实例。在使用DataEntrance解决问题(1)的同时,问题(2)也自然被解决了。让我们来看看DataEntrance的背后玄机。

前篇文章中提到的访问类的基本使用方式并没有被替代,你仍然可以按照以前的方式来使用它,而DataEntrance为我们提供了更简单的使用方式。参见http://blog.csdn.net/zhuweisky/archive/2005/07/29/439291.aspx 可以先对DataEntrance有个感性的认识,这对下面的理解会有帮助。

首先DataEntrance是一个静态类,这样我们在使用它的时候,可以直接通过类名引用其方法,而不需管理DataEntrance的实例。

其次DataEntrance需要在系统启动的时候初始化。

虽然,DataEntrance是一个静态类,但是其需要被初始化,初始化动作的目的就是设定数据库的相关信息,比如连接字符串、数据库类型等。在这里,我们需要考虑,如果在程序运行的过程中,用户更改了数据库的配置信息,那么我们的DataEntrance也应该能随其改变以适应最新的情况。为了使DataEntrance能接收这样的通知,我设计了IDataBaseInfoMgr接口,该接口发布了DbConfigChanged事件。其定义如下:

public   interface  IDataBaseInfoMgr
    
{
        
string GetConnString(out DataBaseType dbType) ;
        
event  EventHandler DbConfigChanged ;
    }

我把该接口的引用作为DataEntrance初始化的参数传进去,这样DataEntrance就能在数据库配置信息改变时,做相应的调整了。看看DataEntrance的初始化方法的声明:

public   static   bool  InitializeDBAccesserFactory(IDataBaseInfoMgr dbInfoMgr ,IDBAccesserFactory dbFactory )

其中,IDBAccesserFactory接口有什么用了?我们先看看DataEntrance这一示例用法:

其中, IDBAccesserFactory 接口有什么用了?我们先看看 DataEntrance 这一示例用法:
string  name  =  DataEntrance.GetFieldValue( typeof (MobileUser) , " 0 "  , " Name " ).ToString() ;

我们传入的第一个参数是我们的数据对象类型,也就是说我们需要根据数据对象的类型来得到对应的访问类实例,这需要通过反射来完成,IDBAccesserFactory就是做这件事的,并且IDBAccesserFactory还会缓存创建过的访问类对象的实例。由于反射无法穿越自定义的程序集,所以我将XDBAccesserFactory.cs放在了本地文件夹EnterpriseServerBase.DataAccess中。IDBAccesserFactory接口的定义如下:

我们传入的第一个参数是我们的数据对象类型,也就是说我们需要根据数据对象的类型来得到对应的访问类实例,这需要通过反射来完成, IDBAccesserFactory 就是做这件事的,并且 IDBAccesserFactory 还会缓存创建过的访问类对象的实例。由于反射无法穿越自定义的程序集,所以我将 XDBAccesserFactory.cs 放在了本地文件夹 EnterpriseServerBase.DataAccess 中。 IDBAccesserFactory 接口的定义如下:

public   interface  IDBAccesserFactory
    
{        
        
//如果connStr经常变化,可传入null 。如果是Ole,则connStr为access文件的路径。
        
//cachAccesser表示是否缓存创建的实例,
        void Initialize(DataBaseType dbType ,string connStr ,bool cachAccesser) ;
        
        
//采用dataClassType作为参数是为了在编译时发现类型不存在的错误,比如删除了一个表及对应数据类,则相关的其它代码将无法通过编译
        IDBAccesser CreateDBAccesser(Type dataClassType) ;        
        IDBAccesser CreateDBAccesser(DataBaseType dbType , 
string connStr , Type dataClassType);

        
//适用于dealer与dataclass命名空间不同的情况
        IDBAccesser CreateDBAccesser(Type dataClassType ,string dealerNamespace) ;        
    }

那么,CreateDBAccesser方法是如何根据数据对象类的名字来创建对应的访问者实例的了?因为XcodeFactory生成的数据层代码有这样一个约定:如果数据对象类的名字是Abc,那么Ole的访问者就是AbcOleDealerSqlServer的访问者就是AbcSqlDealer,并且数据对象类和访问者处于同一命名空间中,所以一旦IDBAccesserFactory知道了数据对象类的类型,自然就可以根据数据库类型推倒出访问者类型,然后通过反射,就可以创建访问者实例了。

 

    再次IDBAccesser 接口中的方法基本上都可以在DataEntrance中找到对应的静态方法,只不过这个静态方法比IDBAccesser 的对应方法多了一个参数,这个参数就是数据对象类的类型,正如上面提到的,这个类型用于IDBAccesserFactory动态的产生访问者实例。所以,以前我们需要先new一个访问者出来,然后再进行数据访问操作,现在不用这么麻烦了。对数据层的操作,我们完全可以通过DataEntrance进行。

下面的例子是根据学生的ID找到其导师的名字,以前需要这样做:

IDBAccesser  studentDealer   =  dbAccesserFactory. CreateDBAccesser ( typeof (student)) ;
            Student stu      
=  (Student)studentDealer.GetAObject( " Where ID = '001' " ) ;
            IDBAccesser  mentorDealer    
=  dbAccesserFactory. CreateDBAccesser ( typeof (Mentor)) ;

            Mentor mentor     
=  (Mentor)mentorDealer.GetAObject( string .Format( " Where ID = '{0}' "  ,stu.MentorID)) ;
            
string  theName      =  mentor.Name ;

            
// 使用DataEntrance可以这样做:
             string  mentorID  =  DataEntrance.GetFieldValue( typeof (Student) , " 001 "  , " MentorID " ).ToString() ;
            
string  theName   =  DataEntrance.GetFieldValue( typeof (Mentor) ,mentorID , " Name " ).ToString() ;

使用DataEntrance的优势很明显了,而且我们的代码完全不依赖于数据库的类型。使用何种数据库类型只需要在一个地方指定,那就是IDBAccesserFactoryInitialize方法的参数中。

使用 DataEntrance 的优势很明显了,而且我们的代码完全不依赖于数据库的类型。使用何种数据库类型只需要在一个地方指定,那就是 IDBAccesserFactory Initialize 方法的参数中。

 

    最后,我们需要进一步挖掘DataEntranceDataEntrance正如其名,是我们访问数据层的入口。我想使我们与数据层的所有交互都通过DataEntrance进行,而且我们也不想再关心IDBAccesserFactory了。所以我决定将一切都封装到DataEntrance的静态方法中(比如IDBAccesserFactory的初始化),这样能最大限度的方便我们的使用。所以我们在系统启动的时候,需要调用DataEntrance的初始化方法,该方法就包含了对IDBAccesserFactory初始化方法的调用。到现在为止,我们已经完全可以通过DataEntrance来完成一切的数据层的访问操作了。下面将DataEntrance主要的静态方法的声明贴出来:

/// <summary>
    
/// DataEntrance 是使用EnterpriseServerBase.DataAccess的基础入口,对XCodeFactory生成的数据层代码提供最大的支持,
    
/// 简化用户对该类库的使用。
    
/// (1)用户必须实现IDataBaseInfoMgr接口用于提供数据库类型和连接信息。
    
/// (2)dbFactory 直接传入new XDBAccesserFactory() 即可。
    
/// (3)请确保在主窗体的构造函数中或Main方法中调用了DataEntrance.InitializeDBAccesserFactory() ;
    
/// (4)凡是需要得到IDBAccesser实例的地方,请调用DataEntrance.CreateDBAccesser() ;
    
/// (5)若是只需要使用IDBAccesser接口的query和order接口,可以使用DataEntrance中提供的更简单的对应方法
    
/// </summary>

     public   class  DataEntrance
    
{        
        
public static bool InitializeDBAccesserFactory(IDataBaseInfoMgr dbInfoMgr ,IDBAccesserFactory dbFactory );
    
        
public static IDBAccesser CreateDBAccesser(Type dataClassType) ;
        
        
#region Query
        
public static object GetFieldValue(Type objType ,string theID ,string fieldName);

        
public static DataSet GetDataSet(Type objType ,string select_str) ;

        
public static object GetAObject(Type objType ,string whereStr);

        
public static object GetAObjectEspecial(Type objType ,string theID);

        
public static object[] GetObjects(Type objType ,string whereStr);

        
public static object[] GetObjectsWithoutBolb(Type objType ,string whereStr);

        
public static bool FillBlobData(Type objType ,object obj) ;
        
#endregion


        
#region Order
        
public static void Insert(Type objType ,object obj ,IDbTransaction trans) ;

        
public static object InsertReturnIdentity(Type objType ,object obj ,IDbTransaction trans ) ;

        
public static void InsertBatch(Type objType ,ArrayList objs ,IDbTransaction trans);

        
public static void InsertBatch(Type objType ,object[] objs ,IDbTransaction trans);

        
public static void Update(Type objType ,object obj ,IDbTransaction trans) ;

        
public static bool UpdateFieldValue(Type objType ,object theID ,string fieldName ,object newVal ,IDbTransaction trans);

        
public static void Delete(Type objType ,object ID ,IDbTransaction trans)  //ID一般为int或string类型    
        #endregion

        
        
public static IADOBase GetADOBase();
    
        
public static IDataPaginationManager GetPaginationMgr(Type objType ,string selectStr ,string complexID_Name ,int page_size);
        
        
public static ITransactionHelper GetTransactionHelper();
        
        
private static IDBAccesser GetDestDealer(Type dataObjType);        
    }

 

如果你只是想使用XcodeFactory生成的数据层代码,而不想关心其它的东西,那么了解一下DataEntrance就足够了,如果你想知道这些代码内部是如何工作的,还有哪些更高级的使用方法等高级内容,请关注我的使用手册(下),谢谢!

 

附注:关于自动生成的数据层代码.cs文件的组织

我的习惯是,为数据层建立一个目录叫做DataAccessLayer XcodeFactory生成的所有cs文件都放在这个目录下的某个子目录下。对应数据库中的每一个表(也对应一个cfp文件),在DataAccessLayer目录下建立一个对应的文件夹,这个文件夹下放有该cfp文件生成的数据对象类和访问类(可能还有自动生成的窗体类),下图是我的PoliceMonitorSystem项目中的文件结构组织截图:(其中蓝色的圈圈中的目录,是从XcodeFactory主菜单=》帮助=》获取DataAccess压缩包解压后得到的)

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值