PostgreSQL的PDF.NET驅(qū)動程序構(gòu)建過程
目前有兩種主要的PostgreSQL的.NET驅(qū)動程序,分別是Npgsql和dotConnector for PostgreSQL(以下簡稱dotConnector),這兩者都是第三方的.NET Provider,本文將大致講解一下這兩個驅(qū)動程序的安裝方式,并講解如何利用它們構(gòu)建PDF.NET的驅(qū)動程序,使得PDF.NET數(shù)據(jù)開發(fā)框架可以支持訪問PostgreSQL數(shù)據(jù)庫。
一、安裝PostgreSQL的.NET驅(qū)動程序
1,Npgsql的安裝:
PostgreSQL數(shù)據(jù)庫程序可以去官網(wǎng)http://www.postgresql.org/下載,在寫本篇文章的時候,***版本已經(jīng)是9.1了,我下載使用的是9.0.4. 下載安裝以后,打開程序 Application Stack Builder,選擇已經(jīng)安裝好的數(shù)據(jù)庫以后,單擊下一步進(jìn)入到如下界面
在Datase Drivers選項中,這里選擇Npgsql v2.0.11-1,其它驅(qū)動程序根據(jù)需要安裝。選擇好以后,按照提示一步步即可完整安裝好.NET的數(shù)據(jù)驅(qū)動程序。
2,dotConnect For PostgreSQL 安裝
在網(wǎng)上搜索一下這個驅(qū)動程序,我是從下面的地址安裝的:http://wzmcc.newhua.com/soft/92182.htm安裝文件名是 dcpostgresqlfree.exe,版本是 5.30.160,安裝的時候會選擇是否將程序集編譯到GAC中。安裝完成以后在安裝目錄會有幾個簡單的示例程序解決方案:
大家可以打開示例程序解決方案看看,都很簡單,具體如何使用可以看本篇文章的下面部分。
#p#
二、構(gòu)建PDF.NET For PostgreSQL驅(qū)動程序
根據(jù)上面的步驟,安裝了.NET的PostgreSQL驅(qū)動程序以后,就可以直接按照示例來訪問PostgreSQL數(shù)據(jù)庫了,但這兩種不同的驅(qū)動程序讓我們難以選擇使用哪一種,而且它們直接提供的ADO.NET實現(xiàn)用起來也不是十分方便,我們有必要將它們包裝一下,簡化使用方式。PDF.NET數(shù)據(jù)開發(fā)框架內(nèi)置了MS DAAB類似的AdoHelper數(shù)據(jù)訪問抽象類,所以只要繼承該類就可以擁有PDF.NET強(qiáng)大的數(shù)據(jù)訪問能力。
1,包裝Ngpsql驅(qū)動程序
下面以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數(shù)據(jù)訪問類
- /// </summary>
- public class PostgreSQL : AdoHelper
- {
- /// <summary>
- /// 默認(rèn)構(gòu)造函數(shù)
- /// </summary>
- public PostgreSQL()
- {
- //
- // TODO: 在此處添加構(gòu)造函數(shù)邏輯
- //
- }
- /// <summary>
- /// 獲取當(dāng)前數(shù)據(jù)庫類型的枚舉
- /// </summary>
- public override PWMIS.Common.DBMSType CurrentDBMSType
- {
- get { return PWMIS.Common.DBMSType.PostgreSQL ; }
- }
- /// <summary>
- /// 創(chuàng)建并且打開數(shù)據(jù)庫連接
- /// </summary>
- /// <returns>數(shù)據(jù)庫連接</returns>
- protected override IDbConnection GetConnection()
- {
- IDbConnection conn = base.GetConnection();
- if (conn == null)
- {
- conn = new NpgsqlConnection (base.ConnectionString);
- //conn.Open ();
- }
- return conn;
- }
- /// <summary>
- /// 獲取數(shù)據(jù)適配器實例
- /// </summary>
- /// <returns>數(shù)據(jù)適配器</returns>
- protected override IDbDataAdapter GetDataAdapter(IDbCommand command)
- {
- IDbDataAdapter ada = new NpgsqlDataAdapter((NpgsqlCommand)command);
- return ada;
- }
- /// <summary>
- /// 獲取一個新參數(shù)對象
- /// </summary>
- /// <returns>特定于數(shù)據(jù)源的參數(shù)對象</returns>
- public override IDataParameter GetParameter()
- {
- return new NpgsqlParameter();
- }
- /// <summary>
- /// 獲取一個新參數(shù)對象
- /// </summary>
- /// <param name="paraName">參數(shù)名</param>
- /// <param name="dbType">參數(shù)數(shù)據(jù)類型</param>
- /// <param name="size">參數(shù)大小</param>
- /// <returns>特定于數(shù)據(jù)源的參數(shù)對象</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 的數(shù)據(jù)源的架構(gòu)信息。
- /// </summary>
- /// <param name="collectionName">集合名稱</param>
- /// <param name="restrictionValues">請求的架構(gòu)的一組限制值</param>
- /// <returns>數(shù)據(jù)庫架構(gòu)信息表</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>
- /// 預(yù)處理SQL語句,語句中不能包含"`"(反引號,tab鍵上面的那個符號)號,如果需要,請使用參數(shù)化查詢。
- /// </summary>
- /// <param name="SQL"></param>
- /// <returns></returns>
- protected override string PrepareSQL(ref string SQL)
- {
- return SQL.Replace("[", "\"").Replace("]", "\"");
- }
- /// <summary>
- /// 獲取或者設(shè)置自增列對應(yīng)的序列名稱
- /// </summary>
- public override string InsertKey
- {
- get
- {
- return string.Format("select currval('\"{0}\"')",base.InsertKey );
- }
- set
- {
- base.InsertKey = value;
- }
- }
- /// <summary>
- /// 定義獲取PostgreSQL的函數(shù)參數(shù)的函數(shù)
- /// <seealso cref="http://www.alberton.info/postgresql_meta_info.html"/>
- /// </summary>
- private void createFunctionArgsInfo()
- {
- //由于函數(shù)定義語句較長,放到了資源文件中
- string sql = PWMIS.PostgreSQLClient.Properties.Resources.sql_function_args;
- this.SqlServerCompatible = false;
- this.ExecuteNonQuery(sql);
- }
- /// <summary>
- /// 獲取函數(shù)的參數(shù)信息
- /// </summary>
- /// <param name="functionName">函數(shù)名</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語句轉(zhuǎn)換成PostgreSQL支持的格式,SQLSERVER使用成對的中括號來限定對象名,而PostgreSQL使用雙引號,尤其在對象名稱使用了大小寫混合的情況。另外程序為了支持獲取數(shù)據(jù)庫的架構(gòu)信息,重寫了AdoHelper的抽象方法GetSchema,有關(guān)PostgreSQL具體獲取表架構(gòu)信息的內(nèi)容,請參看 http://www.alberton.info/postgresql_meta_info.html 。
#p#
2,包裝dotConnect驅(qū)動程序
程序代碼與使用Npgsql類似,區(qū)別主要是將上面代碼中的Npgsql字樣替換成PgSql即可,引用Devart.Data.dll,Devart.Data.PostgreSql.dll,使用下面的名稱空間:
- using Devart.Data.PostgreSql;
由于dotConnect的驅(qū)動程序采用Oracle驅(qū)動程序的風(fēng)格,要求SQL語句的參數(shù)使用“:”作為參數(shù)名稱,而不是SqlServer樣式的“@”,所以下面的方法需要重寫:
- /// <summary>
- /// 預(yù)處理SQL語句,語句中不能包含中括號,如果需要,請使用參數(shù)化查詢。
- /// </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驅(qū)動程序也做好了。
三、使用PDF.NET For PostgreSQL驅(qū)動程序
1,使用配置
假定上面使用Npgsql和dotConnect驅(qū)動的程序分別是 PWMIS.PostgreSQLClient 程序集中的程序,名稱分別是
PWMIS.DataProvider.Data.PostgreSQL
PWMIS.DataProvider.Data.dotConnectPostgreSQL
那么我們在應(yīng)用程序配置文件里面如下使用即可:
使用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"/>
#p#
2,執(zhí)行效率區(qū)別
使用這兩個不同的提供程序數(shù)據(jù)訪問效率有什么區(qū)別呢?經(jīng)過測試,它們之間僅有細(xì)微的差別,Npgsql略微勝出,下面是測試程序建立過程:
首先在SqlMap.config文件中建立一個PostgreSQL的數(shù)據(jù)訪問腳本:
- <Select CommandName="GetFundFeat" Method="" CommandType="Text" Description="獲取業(yè)績" ResultClass="DataSet">
- <![CDATA[SELECT * FROM GetFundTrend_FundAnalysis_FundFeat (#currentJJDM:String#,#OtherJJDM:String#)]]>
- </Select>
然后使用集成開發(fā)工具的代碼生成器生成一個類中下面的方法:
- public DataSet GetFundFeat(String currentJJDM , String OtherJJDM )
- {
- //獲取命令信息
- CommandInfo cmdInfo=Mapper.GetCommandInfo("GetFundFeat");
- //參數(shù)賦值,推薦使用該種方式;
- cmdInfo.DataParameters[0].Value = currentJJDM;
- cmdInfo.DataParameters[1].Value = OtherJJDM;
- //參數(shù)賦值,使用命名方式;
- //cmdInfo.SetParameterValue("@currentJJDM", currentJJDM);
- //cmdInfo.SetParameterValue("@OtherJJDM", OtherJJDM);
- //執(zhí)行查詢
- return CurrentDataBase.ExecuteDataSet(CurrentDataBase.ConnectionString, cmdInfo.CommandType, cmdInfo.CommandText , cmdInfo.DataParameters);
- //
- }//End Function
***以不同的Pgsql驅(qū)動程序運行程序,查看執(zhí)行的SQL日志:
使用dotConnect訪問:
- //2011/5/30 16:52:44 @AdoHelper 執(zhí)行命令:
- SQL="SELECT * FROM GetFundTrend_FundAnalysis_FundFeat (:currentJJDM,:OtherJJDM)"
- //命令類型:Text
- //2個命令參數(shù):
- 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 執(zhí)行命令:
- SQL="SELECT * FROM GetFundTrend_FundAnalysis_FundFeat (@currentJJDM,@OtherJJDM)"
- //命令類型:Text
- //2個命令參數(shù):
- Parameter["@currentJJDM"] = "KF0180" //DbType=String
- Parameter["@OtherJJDM"] = "000001,399001,H11020,000300" //DbType=String
- //2011/5/30 16:58:17 @AdoHelper :Execueted Time(ms):405
原文鏈接:http://www.cnblogs.com/bluedoctor/archive/2011/05/30/2063494.html
【編者推薦】