设为首页 收藏本站
查看: 794|回复: 0

[经验分享] PostgreSQL的PDF.NET驱动程序构建过程

[复制链接]

尚未签到

发表于 2016-11-21 09:01:12 | 显示全部楼层 |阅读模式
  目前有两种主要的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,选择已经安装好的数据库以后,单击下一步进入到如下界面 DSC0000.png
  在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中。安装完成以后在安装目录会有几个简单的示例程序解决方案:
DSC0001.png

  大家可以打开示例程序解决方案看看,都很简单,具体如何使用可以看本篇文章的下面部分。
  二、构建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语句的参数使用&#8220;:&#8221;作为参数名称,而不是SqlServer样式的&#8220;@&#8221;,所以下面的方法需要重写:


        /// <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

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-303218-1-1.html 上篇帖子: Spring 连接 PostgreSQL 下篇帖子: postgresql 内存分配
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表