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

本文涉及的产品
云数据库 RDS SQL Server,基础系列 2核4GB
云原生数据库 PolarDB PostgreSQL 版,标准版 2核4GB 50GB
云原生数据库 PolarDB MySQL 版,通用型 2核8GB 50GB
简介:

目前有两种主要的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

 

 

 

 

    本文转自深蓝医生博客园博客,原文链接:http://www.cnblogs.com/bluedoctor/archive/2011/05/30/2063494.html,如需转载请自行联系原作者




相关实践学习
使用PolarDB和ECS搭建门户网站
本场景主要介绍如何基于PolarDB和ECS实现搭建门户网站。
阿里云数据库产品家族及特性
阿里云智能数据库产品团队一直致力于不断健全产品体系,提升产品性能,打磨产品功能,从而帮助客户实现更加极致的弹性能力、具备更强的扩展能力、并利用云设施进一步降低企业成本。以云原生+分布式为核心技术抓手,打造以自研的在线事务型(OLTP)数据库Polar DB和在线分析型(OLAP)数据库Analytic DB为代表的新一代企业级云原生数据库产品体系, 结合NoSQL数据库、数据库生态工具、云原生智能化数据库管控平台,为阿里巴巴经济体以及各个行业的企业客户和开发者提供从公共云到混合云再到私有云的完整解决方案,提供基于云基础设施进行数据从处理、到存储、再到计算与分析的一体化解决方案。本节课带你了解阿里云数据库产品家族及特性。
相关文章
|
存储 Shell Linux
快速上手基于 BaGet 的脚本自动化构建 .net 应用打包
本文介绍了如何使用脚本自动化构建 `.net` 应用的 `nuget` 包并推送到指定服务仓库。首先概述了 `BaGet`——一个开源、轻量级且高性能的 `NuGet` 服务器,支持多种存储后端及配置选项。接着详细描述了 `BaGet` 的安装、配置及使用方法,并提供了 `PowerShell` 和 `Bash` 脚本实例,用于自动化推送 `.nupkg` 文件。最后总结了 `BaGet` 的优势及其在实际部署中的便捷性。
605 10
|
4月前
|
JSON 编解码 API
Go语言网络编程:使用 net/http 构建 RESTful API
本章介绍如何使用 Go 语言的 `net/http` 标准库构建 RESTful API。内容涵盖 RESTful API 的基本概念及规范,包括 GET、POST、PUT 和 DELETE 方法的实现。通过定义用户数据结构和模拟数据库,逐步实现获取用户列表、创建用户、更新用户、删除用户的 HTTP 路由处理函数。同时提供辅助函数用于路径参数解析,并展示如何设置路由器启动服务。最后通过 curl 或 Postman 测试接口功能。章节总结了路由分发、JSON 编解码、方法区分、并发安全管理和路径参数解析等关键点,为更复杂需求推荐第三方框架如 Gin、Echo 和 Chi。
|
10月前
|
前端开发 C# 开发者
.NET使用Umbraco CMS快速构建一个属于自己的内容管理系统
.NET使用Umbraco CMS快速构建一个属于自己的内容管理系统
135 12
|
10月前
|
弹性计算 开发框架 安全
基于云效 Windows 构建环境和 Nuget 制品仓库进行 .Net 应用开发
本文将基于云效 Flow 流水线 Windows 构建环境和云效 Packages Nuget 制品仓库手把手教你如何开发并部署一个 .NET 应用,从环境搭建到实战应用发布的详细教程,帮助你掌握 .NET 开发的核心技能。
|
11月前
|
Kubernetes Cloud Native Ubuntu
庆祝 .NET 9 正式版发布与 Dapr 从 CNCF 毕业:构建高效云原生应用的最佳实践
2024年11月13日,.NET 9 正式版发布,Dapr 从 CNCF 毕业,标志着云原生技术的成熟。本文介绍如何使用 .NET 9 Aspire、Dapr 1.14.4、Kubernetes 1.31.0/Containerd 1.7.14、Ubuntu Server 24.04 LTS 和 Podman 5.3.0-rc3 构建高效、可靠的云原生应用。涵盖环境准备、应用开发、Dapr 集成、容器化和 Kubernetes 部署等内容。
632 6
|
Kubernetes Cloud Native Linux
如何使用 Containerfile/Dockerfile 构建 .net 镜像?
构建轻量级的 .NET Core 镜像通常涉及到几个关键步骤,主要是选择正确的基础镜像、使用多阶段构建、优化文件结构以及清理不必要的文件。.NET 8 在云原生方面的支持有了显著的增强,这些改进旨在提高性能、减少资源消耗、简化部署流程以及提升应用程序的可观察性和可维护性。
976 5
如何使用 Containerfile/Dockerfile 构建 .net 镜像?
|
设计模式 存储 前端开发
揭秘.NET架构设计模式:如何构建坚不可摧的系统?掌握这些,让你的项目无懈可击!
【8月更文挑战第28天】在软件开发中,设计模式是解决常见问题的经典方案,助力构建可维护、可扩展的系统。本文探讨了.NET中三种关键架构设计模式:MVC、依赖注入与仓储模式,并提供了示例代码。MVC通过模型、视图和控制器分离关注点;依赖注入则通过外部管理组件依赖提升复用性和可测性;仓储模式则统一数据访问接口,分离数据逻辑与业务逻辑。掌握这些模式有助于开发者优化系统架构,提升软件质量。
171 5
|
机器学习/深度学习 人工智能 算法
【悬念揭秘】ML.NET:那片未被探索的机器学习宝藏,如何让普通开发者一夜变身AI高手?——从零开始,揭秘构建智能应用的神秘旅程!
【8月更文挑战第28天】ML.NET 是微软推出的一款开源机器学习框架,专为希望在本地应用中嵌入智能功能的 .NET 开发者设计。无需深厚的数据科学背景,即可实现预测分析、推荐系统和图像识别等功能。它支持多种数据源,提供丰富的预处理工具和多样化的机器学习算法,简化了数据处理和模型训练流程。
281 1
|
存储 缓存 安全
.NET 在金融行业的应用:高并发交易系统的构建与优化之路
【8月更文挑战第28天】在金融行业,交易系统需具备高并发处理、低延迟及高稳定性和安全性。利用.NET构建此类系统时,可采用异步编程提升并发能力,优化数据库访问以降低延迟,使用缓存减少数据库访问频率,借助分布式事务确保数据一致性,并加强安全性措施。通过综合优化,满足金融行业的严苛要求。
287 1
|
大数据 开发工具 开发者
从零到英雄:.NET核心技术带你踏上编程之旅,构建首个应用,开启你的数字世界探险!
【8月更文挑战第28天】本文带领读者从零开始,使用强大的.NET平台搭建首个控制台应用。无论你是新手还是希望扩展技能的开发者,都能通过本文逐步掌握.NET的核心技术。从环境搭建到创建项目,再到编写和运行代码,详细步骤助你轻松上手。通过计算两数之和的小项目,你不仅能快速入门,还能为未来开发更复杂的应用奠定基础。希望本文为你的.NET学习之旅开启新篇章!
104 1

热门文章

最新文章

推荐镜像

更多