PostgreSQL的PDF.NET驱动程序构建过程

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

目前有两种主要的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中。安装完成以后在安装目录会有几个简单的示例程序解决方案:

 

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

#p#

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

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

1,包装Ngpsql驱动程序

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

  1. using System;  
  2. using System.Collections.Generic;  
  3. //using System.Linq;  
  4. using System.Text;  
  5. using System.Data;  
  6. using Npgsql ;  
  7.  
  8. namespace PWMIS.DataProvider.Data  
  9. {  
  10.     /// <summary>  
  11.     /// PostgreSQL数据访问类  
  12.     /// </summary>  
  13.     public class PostgreSQL : AdoHelper  
  14.     {  
  15.         /// <summary>  
  16.         /// 默认构造函数  
  17.         /// </summary>  
  18.         public PostgreSQL()  
  19.         {  
  20.             //  
  21.             // TODO: 在此处添加构造函数逻辑  
  22.             //  
  23.         }  
  24.         /// <summary>  
  25.         /// 获取当前数据库类型的枚举  
  26.         /// </summary>  
  27.         public override PWMIS.Common.DBMSType CurrentDBMSType  
  28.         {  
  29.             get { return PWMIS.Common.DBMSType.PostgreSQL ; }   
  30.         }  
  31.  
  32.         /// <summary>  
  33.         /// 创建并且打开数据库连接  
  34.         /// </summary>  
  35.         /// <returns>数据库连接</returns>  
  36.         protected override IDbConnection GetConnection()  
  37.         {  
  38.             IDbConnection conn = base.GetConnection();  
  39.             if (conn == null)  
  40.             {  
  41.                 conn = new NpgsqlConnection (base.ConnectionString);  
  42.                 //conn.Open ();  
  43.             }  
  44.             return conn;  
  45.         }  
  46.  
  47.         /// <summary>  
  48.         /// 获取数据适配器实例  
  49.         /// </summary>  
  50.         /// <returns>数据适配器</returns>  
  51.         protected override IDbDataAdapter GetDataAdapter(IDbCommand command)  
  52.         {  
  53.             IDbDataAdapter ada = new NpgsqlDataAdapter((NpgsqlCommand)command);  
  54.             return ada;  
  55.         }  
  56.  
  57.         /// <summary>  
  58.         /// 获取一个新参数对象  
  59.         /// </summary>  
  60.         /// <returns>特定于数据源的参数对象</returns>  
  61.         public override IDataParameter GetParameter()  
  62.         {  
  63.             return new NpgsqlParameter();  
  64.         }  
  65.  
  66.         /// <summary>  
  67.         ///  获取一个新参数对象  
  68.         /// </summary>  
  69.         /// <param name="paraName">参数名</param>  
  70.         /// <param name="dbType">参数数据类型</param>  
  71.         /// <param name="size">参数大小</param>  
  72.         /// <returns>特定于数据源的参数对象</returns>  
  73.         public override IDataParameter GetParameter(string paraName, System.Data.DbType dbType, int size)  
  74.         {  
  75.             NpgsqlParameter para = new NpgsqlParameter();  
  76.             para.ParameterName = paraName;  
  77.             para.DbType = dbType;  
  78.             para.Size = size;  
  79.             return para;  
  80.         }  
  81.  
  82.         /// <summary>  
  83.         /// 返回此 NpgsqlConnection 的数据源的架构信息。  
  84.         /// </summary>  
  85.         /// <param name="collectionName">集合名称</param>  
  86.         /// <param name="restrictionValues">请求的架构的一组限制值</param>  
  87.         /// <returns>数据库架构信息表</returns>  
  88.         public override DataTable GetSchema(string collectionName, string[] restrictionValues)  
  89.         {  
  90.             using (NpgsqlConnection conn = (NpgsqlConnection)this.GetConnection())  
  91.             {  
  92.                 conn.Open();  
  93.                 if (restrictionValues == null && string.IsNullOrEmpty(collectionName))  
  94.                     return conn.GetSchema();  
  95.                 else if (restrictionValues == null && !string.IsNullOrEmpty(collectionName))  
  96.                 {  
  97.                     if (collectionName == "Procedures")  
  98.                         return this.getProcedures();  
  99.                     else 
  100.                         return conn.GetSchema(collectionName); //Procedures  
  101.  
  102.                 }  
  103.                 else 
  104.                 {   
  105.                     if (collectionName == "ProcedureParameters")  
  106.                         return getFunctionArgsInfo(restrictionValues[2]);  
  107.                     else 
  108.                         return conn.GetSchema(collectionName, restrictionValues);  
  109.                 }  
  110.             }  
  111.         }  
  112.  
  113.         /// <summary>  
  114.         /// 预处理SQL语句,语句中不能包含"`"(反引号,tab键上面的那个符号)号,如果需要,请使用参数化查询。  
  115.         /// </summary>  
  116.         /// <param name="SQL"></param>  
  117.         /// <returns></returns>  
  118.         protected override string PrepareSQL(ref string SQL)  
  119.         {  
  120.             return SQL.Replace("[""\"").Replace("]""\"");  
  121.         }  
  122.  
  123.         /// <summary>  
  124.         /// 获取或者设置自增列对应的序列名称  
  125.         /// </summary>  
  126.         public override string InsertKey  
  127.         {  
  128.             get 
  129.             {  
  130.                 return string.Format("select currval('\"{0}\"')",base.InsertKey );  
  131.             }  
  132.             set 
  133.             {  
  134.                 base.InsertKey = value;  
  135.             }  
  136.         }  
  137.  
  138.         /// <summary>  
  139.         /// 定义获取PostgreSQL的函数参数的函数  
  140.         /// <seealso cref="http://www.alberton.info/postgresql_meta_info.html"/>  
  141.         /// </summary>  
  142.         private void createFunctionArgsInfo()  
  143.         {  
  144.             //由于函数定义语句较长,放到了资源文件中  
  145.             string sql = PWMIS.PostgreSQLClient.Properties.Resources.sql_function_args;  
  146.             this.SqlServerCompatible = false;  
  147.             this.ExecuteNonQuery(sql);  
  148.         }  
  149.  
  150.         /// <summary>  
  151.         /// 获取函数的参数信息  
  152.         /// </summary>  
  153.         /// <param name="functionName">函数名</param>  
  154.         /// <returns></returns>  
  155.         private DataTable  getFunctionArgsInfo(string functionName)  
  156.         {  
  157.             string sql = string.Format("select * from function_args('{0}','public');", functionName);  
  158.             DataSet ds = null;  
  159.             try 
  160.             {  
  161.                 ds= this.ExecuteDataSet(sql);  
  162.             }  
  163.             catch 
  164.             {  
  165.                 createFunctionArgsInfo();  
  166.                 ds = this.ExecuteDataSet(sql);  
  167.             }  
  168.              
  169.             DataTable dt = ds.Tables[0];  
  170.             dt.Columns["pos"].ColumnName = "ordinal_position";  
  171.             dt.Columns["argname"].ColumnName = "PARAMETER_NAME";  
  172.             dt.Columns["datatype"].ColumnName = "DATA_TYPE";  
  173.             dt.Columns["direction"].ColumnName = "PARAMETER_MODE";  
  174.             dt.Columns.Add("IS_RESULT"typeof(string));  
  175.             dt.Columns.Add("CHARACTER_MAXIMUM_LENGTH"typeof(int));  
  176.  
  177.             foreach (DataRow row in dt.Rows)  
  178.             {  
  179.                 if(row["PARAMETER_NAME"] == DBNull.Value)  row["PARAMETER_NAME"] =  "";   
  180.                 row["IS_RESULT"] = row["PARAMETER_NAME"].ToString() == "RETURN VALUE" ? "YES" : "NO";  
  181.                 row["PARAMETER_MODE"] = row["PARAMETER_MODE"].ToString() == "o" ? "OUT" : row["PARAMETER_MODE"].ToString() == "i" ? "IN" : row["PARAMETER_MODE"];  
  182.             }  
  183.             return dt;  
  184.         }  
  185.  
  186.         private DataTable getProcedures()  
  187.         {  
  188.             string sql = @"SELECT routine_name  
  189.   FROM information_schema.routines  
  190.  WHERE specific_schema NOT IN  
  191.        ('pg_catalog''information_schema')  
  192.    AND type_udt_name != 'trigger';";  
  193.             return this.ExecuteDataSet(sql).Tables[0];  
  194.         }  
  195.     }  
  196. }  

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

#p#

2,包装dotConnect驱动程序

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

  1. using Devart.Data.PostgreSql;  

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

  1. /// <summary>  
  2. /// 预处理SQL语句,语句中不能包含中括号,如果需要,请使用参数化查询。  
  3. /// </summary>  
  4. /// <param name="SQL"></param>  
  5. /// <returns></returns>  
  6. protected override string PrepareSQL(ref string SQL)  
  7. {  
  8.     return SQL.Replace("[""\"").Replace("]""\"").Replace("@",":");  
  9. }  
  10.  
  11. public override string GetParameterChar  
  12. {  
  13.     get 
  14.     {  
  15.         return ":";  
  16.     }  

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

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

1,使用配置

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

PWMIS.DataProvider.Data.PostgreSQL

PWMIS.DataProvider.Data.dotConnectPostgreSQL

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

使用Npgsql访问:

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

使用dotConnect访问:

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

#p#

2,执行效率区别

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

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

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

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

  1. public DataSet GetFundFeat(String currentJJDM  , String OtherJJDM   )   
  2.     {   
  3.             //获取命令信息  
  4.             CommandInfo cmdInfo=Mapper.GetCommandInfo("GetFundFeat");  
  5.             //参数赋值,推荐使用该种方式;  
  6.             cmdInfo.DataParameters[0].Value = currentJJDM;  
  7.             cmdInfo.DataParameters[1].Value = OtherJJDM;  
  8.             //参数赋值,使用命名方式;  
  9.             //cmdInfo.SetParameterValue("@currentJJDM", currentJJDM);  
  10.             //cmdInfo.SetParameterValue("@OtherJJDM", OtherJJDM);  
  11.             //执行查询  
  12.             return CurrentDataBase.ExecuteDataSet(CurrentDataBase.ConnectionString, cmdInfo.CommandType, cmdInfo.CommandText , cmdInfo.DataParameters);  
  13.         //  
  14.     }//End Function  

***以不同的Pgsql驱动程序运行程序,查看执行的SQL日志:

使用dotConnect访问:

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

使用Npgsql访问:

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

原文链接:http://www.cnblogs.com/bluedoctor/archive/2011/05/30/2063494.html

 

【编者推荐】

  1. .net访问PostgreSQL数据库发生“找不到函数名”的问题追踪
  2. PostgreSQL的.NET驱动程序Npgsql中参数对象的一个Bug
  3. PDF.NET数据开发框架实体类操作实例之在PostgreSQL中操作
  4. PostgreSQL数据库管理入门之psql工具篇
责任编辑:艾婧 来源: 博客园
相关推荐

2011-05-19 15:14:49

PostgreSQL

2011-04-26 15:26:38

PostgreSQL

2009-07-06 18:17:46

JDBC驱动程序

2013-10-31 16:29:10

Linux内核

2011-01-06 16:29:08

linuxtasklet机制

2021-11-29 07:55:45

Linux GPIO Linux 系统

2017-03-03 08:40:32

2009-08-12 18:20:39

C#事件驱动程序

2011-01-10 18:21:38

linux编写程序

2010-01-07 13:27:22

Linux驱动程序

2018-11-19 10:15:26

Windows 10WiFi驱动程序

2009-07-20 18:01:38

Oracle JDBC

2021-12-06 07:47:36

Linux 驱动程序Linux 系统

2009-12-07 09:39:04

Linux设备驱动硬件通信

2019-10-22 15:40:34

Windows 10驱动程序Windows

2009-09-04 10:10:33

Visual Basi

2009-06-15 14:18:00

netbeans配置JDBC驱动程序

2022-03-08 09:25:52

数据库系统MongoDB

2010-05-10 15:53:24

Unix系统

2010-02-25 16:09:15

Fedora驱动程序
点赞
收藏

51CTO技术栈公众号