Richie

Sometimes at night when I look up at the stars, and see the whole sky just laid out there, don't you think I ain't remembering it all. I still got dreams like anybody else, and ever so often, I am thinking about how things might of been. And then, all of a sudden, I'm forty, fifty, sixty years old, you know?

NHibernate代码解析 - Driver

    NHibernate-1.2.0.Beta3-debug

    为什么从Driver开始?数据库的使用、多数据库的封装是NHibernate比较底层的东西,因此决定从这里开始。
    多数据库支持的实现无外乎几个方面:使用标准的SQL语句;对客户(Client)封装各类数据库的ADO.NET对象;一些数据库之间特殊性的处理。

    Driver目录下一系列的类,主要目的是封装DbConnection、DbCommand对象的创建,以及Prepare Command,和Command相关的Parameter的操作和处理。
    各类数据库的ADO.NET Provider,都会从DbConnection、DbCommand、DbParameter等这些基础的对象继承,因此对各类数据库ADO.NET Provider的封装使用Facade模式。
   
    Facade模式从上面类图可以看出来。通过配置指定你使用的数据库Driver类,用反射创建Driver实例代替了Factory,Client只使用IDriver或DriverBase类型。
    配置属性hibernate.connection.driver_class从IDriver的具体实现中选择。

    1. IDriver
    最基础的抽象。主要声明的方法:创建IDbConnection、IDbCommand对象;创建IBatcher对象(什么作用?不知道);同一个IDbConnection对象是否支持同时打开多个IDataReader对象等。
    为什么不使用IDbConnection的CreateCommand方法?有数据库的IDbConnection不支持这个方法?不可能。还是为了避免IDbCommand对象一创建就绑定了IDbConnection对象?
    2. ISqlParameterFormatter
    获取Sql语句中第n个参数的参数名。只声明一个方法string GetParameterName(int index)。
        a.) 后面可以看到对于一个Sql语句,NHinbernate用SqlString进行封装,最主要是处理参数名后帮定。在生成最终数据库可以执行的Sql语句时,需要生成参数名,然后生成最终可执行的sql语句。不同的数据库参数的表示不一样,因此生成参数名这个职责落在Driver对象上或至少跟它密切相关。
        b.) 不仅仅是处理数据库不同参数表示不一样的问题,ISqlParameterFormatter同时也确定了一个参数名生成规则,即按照参数的索引顺序生成参数名。在DriverBase的实现中,假如sql语句中有三个参数,则参数名按照顺序分别是p0、p1、p2,这些参数名被用于生成的sql语句、IDbCommand的Parameters对象中。执行时刻也按照顺序提供各个参数的值。
    Odbc、Oledb等使用单一的一个?号表示参数,SqlServer在参数名前面加@符号表示,Oracle使用:前缀,MySql使用?前缀。
    3. DriverBase
    对IDriver最基本的实现,以及部分实现上的扩展。
    4. OdbcDriver、OleDbDriver、SqlClientDriver
    具体实现。
    这三个类都是直接从DriverBase继承,重载实现DriverBase的CreateConnection()、CreateCommand()等方法。因为.Net Framework已经包含了这几种ADO.NET对象,在实现这些方法时,只须用相应的命名空间直接创建对象即可。对于其它的数据库,NHibernate不能将他们的ADO.NET Provider一一引用到项目里面来,因此通过配置使用反射的方式来创建这些数据库的相关对象,这就是ReflectionBasedDriver的分支。
    5. ReflectionBasedDriver
    提供通过反射创建相应数据库ADO.NET对象的支持。继承的子类在构造函数中提供数据库驱动的Assembly Name、IDbConnection和IDbCommand的类名。ReflectionBasedDriver构造函数根据子类提供的信息,在CreateConnection()和CreateCommand()时就可以使用反射创建对象。
    6. OracleClientDriver、MySqlDataDriver、FirebirdDriver等
    具体实现。

    SqlStringFormatter和NDataReader相关的两个类结合其它部分看。

posted on 2007-01-18 23:56  riccc  阅读(1514)  评论(2编辑  收藏  举报

导航