zoukankan      html  css  js  c++  java
  • PostgreSQL的PDF.NET驱动程序构建过程

    目前有两种主要的PostgreSQL的.NET驱动程序,分别是Npgsql和dotConnector for PostgreSQL(以下简称dotConnector),这两者都是第三方的.NET Provider,本文将大致讲解一下这两个驱动程序的安装方式,并讲解如何利用它们构建PDF.NET的驱动程序,使得PDF.NET数据开发框架可以支持访问PostgreSQL数据库。

    一、安装PostgreSQL的.NET驱动程序

    1,Npgsql的安装:

    PostgreSQL数据库程序可以去官网 http://www.postgresql.org/ 下载,在写本篇文章的时候,最新版本已经是9.1了,我下载使用的是9.0.4. 下载安装以后,打开程序 Application Stack Builder,选择已经安装好的数据库以后,单击下一步进入到如下界面 

    在Datase Drivers选项中,这里选择Npgsql v2.0.11-1,其它驱动程序根据需要安装。选择好以后,按照提示一步步即可完整安装好.NET的数据驱动程序。

    2,dotConnect For PostgreSQL 安装

    在网上搜索一下这个驱动程序,我是从下面的地址安装的:

    http://wzmcc.newhua.com/soft/92182.htm

    安装文件名是 dcpostgresqlfree.exe,版本是 5.30.160,安装的时候会选择是否将程序集编译到GAC中。安装完成以后在安装目录会有几个简单的示例程序解决方案:

    大家可以打开示例程序解决方案看看,都很简单,具体如何使用可以看本篇文章的下面部分。

    二、构建PDF.NET For PostgreSQL驱动程序

    根据上面的步骤,安装了.NET的PostgreSQL驱动程序以后,就可以直接按照示例来访问PostgreSQL数据库了,但这两种不同的驱动程序让我们难以选择使用哪一种,而且它们直接提供的ADO.NET实现用起来也不是十分方便,我们有必要将它们包装一下,简化使用方式。PDF.NET数据开发框架内置了MS DAAB类似的AdoHelper数据访问抽象类,所以只要继承该类就可以拥有PDF.NET强大的数据访问能力。

    1,包装Ngpsql驱动程序

    下面以Npgsql为例,看看如何让PDF.NET支持PostgreSQL。下面是贴出全部代码:

    using System;
    using System.Collections.Generic;
    //using System.Linq;
    using System.Text;
    using System.Data;
    using Npgsql ;

    namespace PWMIS.DataProvider.Data
    {
        
    /// <summary>
        
    /// PostgreSQL数据访问类
        
    /// </summary>
        public class PostgreSQL : AdoHelper
        {
            
    /// <summary>
            
    /// 默认构造函数
            
    /// </summary>
            public PostgreSQL()
            {
                
    //
                
    // TODO: 在此处添加构造函数逻辑
                
    //
            }
            
    /// <summary>
            
    /// 获取当前数据库类型的枚举
            
    /// </summary>
            public override PWMIS.Common.DBMSType CurrentDBMSType
            {
                
    get { return PWMIS.Common.DBMSType.PostgreSQL ; } 
            }

            
    /// <summary>
            
    /// 创建并且打开数据库连接
            
    /// </summary>
            
    /// <returns>数据库连接</returns>
            protected override IDbConnection GetConnection()
            {
                IDbConnection conn 
    = base.GetConnection();
                
    if (conn == null)
                {
                    conn 
    = new NpgsqlConnection (base.ConnectionString);
                    
    //conn.Open ();
                }
                
    return conn;
            }

            
    /// <summary>
            
    /// 获取数据适配器实例
            
    /// </summary>
            
    /// <returns>数据适配器</returns>
            protected override IDbDataAdapter GetDataAdapter(IDbCommand command)
            {
                IDbDataAdapter ada 
    = new NpgsqlDataAdapter((NpgsqlCommand)command);
                
    return ada;
            }

            
    /// <summary>
            
    /// 获取一个新参数对象
            
    /// </summary>
            
    /// <returns>特定于数据源的参数对象</returns>
            public override IDataParameter GetParameter()
            {
                
    return new NpgsqlParameter();
            }

            
    /// <summary>
            
    ///  获取一个新参数对象
            
    /// </summary>
            
    /// <param name="paraName">参数名</param>
            
    /// <param name="dbType">参数数据类型</param>
            
    /// <param name="size">参数大小</param>
            
    /// <returns>特定于数据源的参数对象</returns>
            public override IDataParameter GetParameter(string paraName, System.Data.DbType dbType, int size)
            {
                NpgsqlParameter para 
    = new NpgsqlParameter();
                para.ParameterName 
    = paraName;
                para.DbType 
    = dbType;
                para.Size 
    = size;
                
    return para;
            }

            
    /// <summary>
            
    /// 返回此 NpgsqlConnection 的数据源的架构信息。
            
    /// </summary>
            
    /// <param name="collectionName">集合名称</param>
            
    /// <param name="restrictionValues">请求的架构的一组限制值</param>
            
    /// <returns>数据库架构信息表</returns>
            public override DataTable GetSchema(string collectionName, string[] restrictionValues)
            {
                
    using (NpgsqlConnection conn = (NpgsqlConnection)this.GetConnection())
                {
                    conn.Open();
                    
    if (restrictionValues == null && string.IsNullOrEmpty(collectionName))
                        
    return conn.GetSchema();
                    
    else if (restrictionValues == null && !string.IsNullOrEmpty(collectionName))
                    {
                        
    if (collectionName == "Procedures")
                            
    return this.getProcedures();
                        
    else
                            
    return conn.GetSchema(collectionName); //Procedures

                    }
                    
    else
                    { 
                        
    if (collectionName == "ProcedureParameters")
                            
    return getFunctionArgsInfo(restrictionValues[2]);
                        
    else
                            
    return conn.GetSchema(collectionName, restrictionValues);
                    }
                }
            }

            
    /// <summary>
            
    /// 预处理SQL语句,语句中不能包含"`"(反引号,tab键上面的那个符号)号,如果需要,请使用参数化查询。
            
    /// </summary>
            
    /// <param name="SQL"></param>
            
    /// <returns></returns>
            protected override string PrepareSQL(ref string SQL)
            {
                
    return SQL.Replace("[""\"").Replace("]""\"");
            }

            
    /// <summary>
            
    /// 获取或者设置自增列对应的序列名称
            
    /// </summary>
            public override string InsertKey
            {
                
    get
                {
                    
    return string.Format("select currval('\"{0}\"')",base.InsertKey );
                }
                
    set
                {
                    
    base.InsertKey = value;
                }
            }

            
    /// <summary>
            
    /// 定义获取PostgreSQL的函数参数的函数
            
    /// <seealso cref="http://www.alberton.info/postgresql_meta_info.html"/>
            
    /// </summary>
            private void createFunctionArgsInfo()
            {
                
    //由于函数定义语句较长,放到了资源文件中
                string sql = PWMIS.PostgreSQLClient.Properties.Resources.sql_function_args;
                
    this.SqlServerCompatible = false;
                
    this.ExecuteNonQuery(sql);
            }

            
    /// <summary>
            
    /// 获取函数的参数信息
            
    /// </summary>
            
    /// <param name="functionName">函数名</param>
            
    /// <returns></returns>
            private DataTable  getFunctionArgsInfo(string functionName)
            {
                
    string sql = string.Format("select * from function_args('{0}','public');", functionName);
                DataSet ds 
    = null;
                
    try
                {
                    ds
    = this.ExecuteDataSet(sql);
                }
                
    catch
                {
                    createFunctionArgsInfo();
                    ds 
    = this.ExecuteDataSet(sql);
                }
               
                DataTable dt 
    = ds.Tables[0];
                dt.Columns[
    "pos"].ColumnName = "ordinal_position";
                dt.Columns[
    "argname"].ColumnName = "PARAMETER_NAME";
                dt.Columns[
    "datatype"].ColumnName = "DATA_TYPE";
                dt.Columns[
    "direction"].ColumnName = "PARAMETER_MODE";
                dt.Columns.Add(
    "IS_RESULT"typeof(string));
                dt.Columns.Add(
    "CHARACTER_MAXIMUM_LENGTH"typeof(int));

                
    foreach (DataRow row in dt.Rows)
                {
                    
    if(row["PARAMETER_NAME"== DBNull.Value)  row["PARAMETER_NAME"=  ""
                    row[
    "IS_RESULT"= row["PARAMETER_NAME"].ToString() == "RETURN VALUE" ? "YES" : "NO";
                    row[
    "PARAMETER_MODE"= row["PARAMETER_MODE"].ToString() == "o" ? "OUT" : row["PARAMETER_MODE"].ToString() == "i" ? "IN" : row["PARAMETER_MODE"];
                }
                
    return dt;
            }

            
    private DataTable getProcedures()
            {
                
    string sql = @"SELECT routine_name
      FROM information_schema.routines
     WHERE specific_schema NOT IN
           ('pg_catalog', 'information_schema')
       AND type_udt_name != 'trigger';
    ";
                
    return this.ExecuteDataSet(sql).Tables[0];
            }
        }
    }

     注意上面程序中的 PrepareSQL 方法,它将SQLSERVER格式的SQL语句转换成PostgreSQL支持的格式,SQLSERVER使用成对的中括号来限定对象名,而PostgreSQL使用双引号,尤其在对象名称使用了大小写混合的情况。另外程序为了支持获取数据库的架构信息,重写了AdoHelper的抽象方法GetSchema,有关PostgreSQL具体获取表架构信息的内容,请参看 http://www.alberton.info/postgresql_meta_info.html

    2,包装dotConnect驱动程序

    程序代码与使用Npgsql类似,区别主要是将上面代码中的Npgsql字样替换成PgSql即可,引用Devart.Data.dll,Devart.Data.PostgreSql.dll,使用下面的名称空间:

    using Devart.Data.PostgreSql;

    由于dotConnect的驱动程序采用Oracle驱动程序的风格,要求SQL语句的参数使用“:”作为参数名称,而不是SqlServer样式的“@”,所以下面的方法需要重写:

            /// <summary>
            
    /// 预处理SQL语句,语句中不能包含中括号,如果需要,请使用参数化查询。
            
    /// </summary>
            
    /// <param name="SQL"></param>
            
    /// <returns></returns>
            protected override string PrepareSQL(ref string SQL)
            {
                
    return SQL.Replace("[""\"").Replace("]""\"").Replace("@",":");
            }

            
    public override string GetParameterChar
            {
                
    get
                {
                    
    return ":";
                }
            }

    到此为止,使用dotConnect做PDF.NET的PostgreSQL驱动程序也做好了。

    三、使用PDF.NET For PostgreSQL驱动程序

    1,使用配置

    假定上面使用Npgsql和dotConnect驱动的程序分别是 PWMIS.PostgreSQLClient 程序集中的程序,名称分别是

    PWMIS.DataProvider.Data.PostgreSQL

    PWMIS.DataProvider.Data.dotConnectPostgreSQL

    那么我们在应用程序配置文件里面如下使用即可:

    使用Npgsql访问:

    <add name="ConnectionSetting" connectionString="server=192.168.XX.XX;User Id=postgres;password=XXXX;DataBase=XXDB" providerName="PWMIS.DataProvider.Data.PostgreSQL,PWMIS.PostgreSQLClient"/>

    使用dotConnect访问:

    <add name="ConnectionSetting" connectionString="server=192.168.XX.XX;User Id=postgres;password=XXXX;DataBase=XXDB" providerName="PWMIS.DataProvider.Data.dotConnectPostgreSQL,PWMIS.PostgreSQLClient"/>

    2,执行效率区别

    使用这两个不同的提供程序数据访问效率有什么区别呢?经过测试,它们之间仅有细微的差别,Npgsql略微胜出,下面是测试程序建立过程:

    首先在SqlMap.config文件中建立一个PostgreSQL的数据访问脚本:

    <Select CommandName="GetFundFeat" Method="" CommandType="Text" Description="获取业绩" ResultClass="DataSet">
    <![CDATA[SELECT * FROM GetFundTrend_FundAnalysis_FundFeat (#currentJJDM:String#,#OtherJJDM:String#)]]>
    </Select>

    然后使用集成开发工具的代码生成器生成一个类中下面的方法:

    public DataSet GetFundFeat(String currentJJDM  , String OtherJJDM   ) 
        { 
                
    //获取命令信息
                CommandInfo cmdInfo=Mapper.GetCommandInfo("GetFundFeat");
                
    //参数赋值,推荐使用该种方式;
                cmdInfo.DataParameters[0].Value = currentJJDM;
                cmdInfo.DataParameters[
    1].Value = OtherJJDM;
                
    //参数赋值,使用命名方式;
                
    //cmdInfo.SetParameterValue("@currentJJDM", currentJJDM);
                
    //cmdInfo.SetParameterValue("@OtherJJDM", OtherJJDM);
                
    //执行查询
                return CurrentDataBase.ExecuteDataSet(CurrentDataBase.ConnectionString, cmdInfo.CommandType, cmdInfo.CommandText , cmdInfo.DataParameters);
            
    //
        }//End Function
    最后以不同的Pgsql驱动程序运行程序,查看执行的SQL日志

    使用dotConnect访问:

    //2011/5/30 16:52:44 @AdoHelper 执行命令:
    SQL
    ="SELECT * FROM GetFundTrend_FundAnalysis_FundFeat (:currentJJDM,:OtherJJDM)"
    //命令类型:Text
    //2个命令参数:
    Parameter
    ["currentJJDM"]    =    "KF0355"              //DbType=AnsiString
    Parameter
    ["OtherJJDM"]    =    "000001,399001,H11020,000300"              //DbType=AnsiString
    //
    2011/5/30 16:52:44 @AdoHelper :Execueted Time(ms):448

    使用Npgsql访问:

    //2011/5/30 16:58:17 @AdoHelper 执行命令:
    SQL
    ="SELECT * FROM GetFundTrend_FundAnalysis_FundFeat (@currentJJDM,@OtherJJDM)"
    //命令类型:Text
    //2个命令参数:
    Parameter
    ["@currentJJDM"]    =    "KF0180"              //DbType=String
    Parameter
    ["@OtherJJDM"]    =    "000001,399001,H11020,000300"              //DbType=String
    //
    2011/5/30 16:58:17 @AdoHelper :Execueted Time(ms):405

    有关PDF.NET数据开发框架的详细信息,请看官网说明:http://www.pwmis.com/sqlmap

  • 相关阅读:
    【The VC Dimension】林轩田机器学习基石
    N天学习一个Linux命令之ln
    charles支持https抓包
    N天学习一个Linux命令之grep
    N天学习一个Linux命令之帮助命令:man
    一个神奇的PHP框架:Phalcon 之编译安装
    让我们加密吧Let's encrypt
    会员卡系统接入微信卡券那些事儿
    Windows安装php Oracle扩展
    Bitnami LNMP集成包安装简单总结
  • 原文地址:https://www.cnblogs.com/bluedoctor/p/2063494.html
Copyright © 2011-2022 走看看