Microsoft MVP성태의 닷넷 이야기
개발 환경 구성: 90. 닷넷에서 접근해보는 PostgreSQL DB [링크 복사], [링크+제목 복사],
조회: 99705
글쓴 사람
정성태 (techsharer at outlook.com)
홈페이지
첨부 파일
 
(연관된 글이 4개 있습니다.)
닷넷에서 접근해보는 PostgreSQL DB

드디어, "PostgreSQL" 데이터베이스를 사용하고 있는 예비 고객사에서 ^^ "제니퍼 닷넷 APM 솔루션"에서 PostgreSQL DB 접근에 대한 모니터링이 가능한지 문의가 들어왔습니다. 그래서 이렇게 PostgreSQL을 처음 설치하고 만져보았는데요. 오호~~~ "관계형 데이터베이스"들이 SQL 쿼리를 지원하고 닷넷의 경우에는 .NET Data Provider를 위한 인터페이스들이 강제되어 있다 보니 기본적인 사용법이 그다지 어렵지 않더군요.

물론, 제가 바닥부터 ^^ PostgreSQL 접근을 알아본 것은 아니고 아래의 글에서부터 시작을 했습니다.

Using PostgreSQL in your C# (.NET) application (An introduction)
; http://www.codeproject.com/KB/database/afppostgresqlintro.aspx

당연히 PostgreSQL 데이터베이스를 서버에 설치부터 해야할텐데, 다음의 경로에서 윈도우 버전의 설치 파일을 다운로드 할 수 있습니다.

Download PostgreSQL 
; http://www.enterprisedb.com/products/pgdownload.do#windows

제 경우에는 x64 운영체제에 설치하기 때문에 "Win x86-64" 아이콘을 눌러서 다운로드 받은 후 설치를 했습니다. 다행히 설치는 무척 간단합니다. ^^ 여느 DB처럼, superuser를 위한 암호를 묻고, 기본 접속 포트는 5432로 설치를 마친 후 SQL 서버의 "Management Studio"와 같은 도구와 유사한 "시작" / "PostgreSQL 9.0" / "pgAdmin III" 프로그램을 실행해서 GUI 환경에서 관리를 해줄 수 있습니다.

관리방식도 꽤 직관적입니다. 누구나 한번쯤 아래와 같이 "오른쪽 마우스 버튼"을 눌러서 "Connect"를 실행해 볼 것이고,

postgresql_dotnet_1.png

설치 시 입력했던 관리자 암호를 입력한 후,

postgresql_dotnet_2.png

연결 문자열에 사용할 테스트용 사용자 계정(ID: testuser)을 아래와 같이 "Login Roles" 노드에서 생성할 수 있습니다.

postgresql_dotnet_3.png

"Database" 노드에서는 새로운 DB를 생성(Name: testdb, Owner: testuser)해 줄 수 있고,

postgresql_dotnet_4.png

생성된 "testdb" 하위 노드의 "Schemas / public / Tables" 에서 테이블을 생성할 수 있습니다.

postgresql_dotnet_5.png

Name: TestTable
Owner: testuser


"New Table..." 대화창의 "Columns" 탭에서 "Add" 버튼을 눌러 다음과 같이 "칼럼"을 추가해 주는 것으로 테스트 환경 구축은 거의 완료가 됩니다.

postgresql_dotnet_6.png

tid: bigserial NOT NULL
name: character varying(150) NOT NULL
age: integer NOT NULL


Primary Key는 "TestTable" 노드를 마우스 오른쪽 버튼 클릭해서 "New Object" / "New Primary Key" 메뉴 선택으로 지정해 줄 수 있습니다. 그 외에 SQL Server와의 변환 체계는 다음의 글을 참고하시면 되겠습니다.

Conversion of Microsoft SQL/ASP applications to PostgreSQL
; http://wiki.postgresql.org/images/e/e4/5.pdf




설치 및 테스트용 DB 구성을 정상적으로 서버에서 마쳤으면, 이제 개발자 PC에 PostgreSQL 서버를 위한 ".NET Data Provider"를 다운로드 받아야 하는데, 다음의 경로에서 C#으로 구현된 오픈소스 "Npgsql"을 구할 수 있습니다.

Npgsql - a .Net data provider for Postgresql
; http://pgfoundry.org/projects/npgsql

다운로드 Npgsql
; http://pgfoundry.org/frs/?group_id=1000140&release_id=958

Microsoft .NET Framework을 위해서 3가지 링크가 제공되는데요.

  1. Npgsql2.0.11-bin-ms.net.zip 464 KB 1,540 Any .zip
  2. Npgsql2.0.11-bin-ms.net3.5sp1.zip 511 KB 1,393 Any .zip
  3. Npgsql2.0.11-bin-ms.net4.0.zip

음... 2번과 3번의 차이는 쉽게 알겠는데 1번은 왜 있는지 잘 모르겠군요. 그냥 무시하고 ^^ 2번과 3번 중에서 원하는 것을 받아 압축을 해제한 후, 다음의 2개 파일만 여러분들의 웹 사이트 프로젝트에 복사해서 참조를 하시면 됩니다. (또는 GAC에 등록을 해주거나.)

  • Mono.Security.dll
  • Npgsql.dll

이렇게 마치고, 처음 연결문자열을 다음과 같이 설정하고 접속을 했는데,

string connectionString = "Server=testpc;Port=5432;User Id=testuser;Password=testuser;Database=testdb";
using (NpgsqlConnection connection = new NpgsqlConnection())
{
    connection.ConnectionString = connectionString;
    connection.Open();

지금까지 너무 쉽긴 했지요. ^^; 아래와 같이 오류가 발생합니다.

System.IO.IOException occurred
  Message=Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host.
  Source=System
  StackTrace:
       at System.Net.Sockets.NetworkStream.Read(Byte[] buffer, Int32 offset, Int32 size)
       at System.IO.BufferedStream.ReadByte()
       at Npgsql.NpgsqlState.<ProcessBackendResponses_Ver_3>d__a.MoveNext() in C:\...\NpgsqlState.cs:line 665
  InnerException: System.Net.Sockets.SocketException
       Message=An existing connection was forcibly closed by the remote host
       Source=System
       ErrorCode=10054
       NativeErrorCode=10054
       StackTrace:
            at System.Net.Sockets.Socket.Receive(Byte[] buffer, Int32 offset, Int32 size, SocketFlags socketFlags)
            at System.Net.Sockets.NetworkStream.Read(Byte[] buffer, Int32 offset, Int32 size)
       InnerException: 

기본값이 SSL 연결만 허용하기 때문인데, "pgAdmin III" 도구에서 "Tools" / "Server Configuration" / "postgresql.conf" 메뉴를 선택하고 아래와 같이 "SSL off" 옵션을 허용시켜 주면 됩니다.

postgresql_dotnet_7.png

아니... ^^; 그래도 다음과 같이 오류가 발생하더군요.

Npgsql.NpgsqlException was unhandled by user code
  Message=FATAL: 28000: no pg_hba.conf entry for host "192.168.0.132", user "testuser", database "testdb", SSL off
  Source=Npgsql
  ErrorCode=-2147467259
  BaseMessage=no pg_hba.conf entry for host "192.168.0.132", user "testuser", database "testdb", SSL off
  Code=28000
  Detail=""
  ErrorSql=""
  File=.\src\backend\libpq\auth.c
  Hint=""
  Line=464
  Position=""
  Routine=ClientAuthentication
  Severity=FATAL
  Where=""
  StackTrace:
       at Npgsql.NpgsqlState.<ProcessBackendResponses_Ver_3>d__a.MoveNext() in C:\...\NpgsqlState.cs:line 686
       at Npgsql.NpgsqlState.IterateThroughAllResponses(IEnumerable`1 ienum) in C:\...\NpgsqlState.cs:line 319
       at Npgsql.NpgsqlState.ProcessBackendResponses(NpgsqlConnector context) in C:\...\NpgsqlState.cs:line 314
       at Npgsql.NpgsqlConnectedState.Startup(NpgsqlConnector context) in C:\...\NpgsqlConnectedState.cs:line 52
       at Npgsql.NpgsqlConnector.Open() in C:\...\NpgsqlConnector.cs:line 656
       at Npgsql.NpgsqlConnectorPool.GetPooledConnector(NpgsqlConnection Connection) in C:\...\NpgsqlConnectorPool.cs:line 423
       at Npgsql.NpgsqlConnectorPool.RequestPooledConnectorInternal(NpgsqlConnection Connection) in C:\...\NpgsqlConnectorPool.cs:line 226
       at Npgsql.NpgsqlConnectorPool.RequestPooledConnector(NpgsqlConnection Connection) in C:\...\NpgsqlConnectorPool.cs:line 178
       at Npgsql.NpgsqlConnectorPool.RequestConnector(NpgsqlConnection Connection) in C:\...\NpgsqlConnectorPool.cs:line 158
       at Npgsql.NpgsqlConnection.Open() in C:\...\NpgsqlConnection.cs:line 543
       at Jennifer40.WebSiteTest.postgreSQLTest.Page_Load(Object sender, EventArgs e) in D:\workshop\Jennifer\Sources\Agent\UnitTest\Jennifer40.WebSiteTest\postgreSQLTest.aspx.cs:line 23
       at System.Web.Util.CalliHelper.EventArgFunctionCaller(IntPtr fp, Object o, Object t, EventArgs e)
       at System.Web.Util.CalliEventHandlerDelegateProxy.Callback(Object sender, EventArgs e)
       at System.Web.UI.Control.OnLoad(EventArgs e)
       at System.Web.UI.Control.LoadRecursive()
       at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)
  InnerException: 

음... 용서해줄 수 있습니다. 기본적인 "Lockdown" 보안 정책은 충분히 이해해 줄 수 있거든요. ^^

검색을 해보니까, PostgreSQL 서버는 접속하려는 측의 IP를 별도로 등록해 주거나, 모든 IP로부터의 접속을 허용한다는 식의 설정을 명시적으로 해주어야 한다고 나옵니다.

그래서, "pgAdmin III" 도구에서 "Tools" / "Server Configuration" / "pg_hba.conf" 메뉴를 선택하고 다음과 같이 NpgsqlConnection 개체를 사용하는 클라이언트 측의 컴퓨터 IP를 등록해 주었습니다.

postgresql_dotnet_8.png

host testdb all 192.168.0.132/32 md5


보시는 것처럼 CIDR 방식으로 지정하는 것이 가능하기 때문에, 일정한 IP 대역을 선택하는 것도 가능합니다. 예를 들어, 다음과 같이 해주면 192.168.0.*의 모든 컴퓨터로부터 접속을 허용합니다.

host     testdb  all     192.168.0.0/24  md5

설정을 변경한 후에는 "서비스 관리자"에서 "postgresql-x64-9.0" NT 서비스를 재시작 해주어야 합니다.

기타의 보다 자세한 사항은 다음의 문서를 보시면 도움이 될 것입니다. ^^

PostgreSQL 8.1.22 Documentation
- Chapter 20. Client Authentication
; http://www.postgresql.org/docs/8.1/interactive/client-authentication.html

물론, 이렇게 적용하고 난 후에는 정상적으로 NpgsqlConnection 연결이 되었고 그 외의 NpgsqlCommand, NpgsqlParameter, NpgsqlDataReader 개체는 아래의 예제 코드에서 보는 것처럼, 예의 "@MyParam"이 아닌 ":MyParam"과 같이 파라미터를 지원하는 차이만을 제외하고는 늘 해오던 수준에서 해결이 되었습니다.

using (NpgsqlConnection connection = new NpgsqlConnection())
{
    connection.ConnectionString = connectionString;
    connection.Open();

    NpgsqlCommand command = new NpgsqlCommand();

    command.Connection = connection;
    command.CommandText = "SELECT * FROM TestTable WHERE :MyParam is not null";
    command.Parameters.Add(new NpgsqlParameter("MyParam", "test"));

    NpgsqlDataReader reader = command.ExecuteReader();
    if (reader != null)
    {
        while (reader.Read())
        {
        }

        reader.Close();
    }
}




한가지, 시행착오를 더 설명드려야겠군요. ^^

"pgAdmin III" 도구에서 테이블 명을 "TestTable"과 같이 대소문자를 섞어서 지정한 경우 다음과 같은 쿼리를 NpgsqlCommand 개체에 지정해서 실행하면 오류가 발생합니다.

SELECT * FROM TestTable

오류 내용은 다음과 같습니다.

Npgsql.NpgsqlException was unhandled by user code
  Message=ERROR: 42P01: relation "testtable" does not exist
  Source=Npgsql
  ErrorCode=-2147467259
  BaseMessage=relation "testtable" does not exist
  Code=42P01
  Detail=""
  ErrorSql=SELECT * FROM TestTable WHERE ((E'test')) is not null AND 1 = 1 AND 'A' = 'A'
  File=.\src\backend\parser\parse_relation.c
  Hint=""
  Line=857
  Position=15
  Routine=parserOpenTable
  Severity=ERROR
  Where=""
  StackTrace:
  ...[생략]...
       at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)
  InnerException: 

해답은 아래에서 찾아보니 나오는데요.

Re: Database, Table Names are resulting in lowercase
; http://archives.postgresql.org/pgsql-admin/2004-06/msg00324.php

명시적으로 "쿼리문"에 포함된 테이블명을 대소문자로 인식시키려면 다음과 같이 쿼리를 바꿔주어야 합니다.

SELECT * FROM "TestTable"

C#의 경우, 아래와 같이 설정됩니다.

command.CommandText = "SELECT * FROM \"TestTable\"";

아니면, 그냥 속편하게 "pgAdmin III" 도구에서 테이블 생성할 때 소문자로만 이름을 줘도 되겠고.




[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]

[연관 글]






[최초 등록일: ]
[최종 수정일: 6/28/2023]

Creative Commons License
이 저작물은 크리에이티브 커먼즈 코리아 저작자표시-비영리-변경금지 2.0 대한민국 라이센스에 따라 이용하실 수 있습니다.
by SeongTae Jeong, mailto:techsharer at outlook.com

비밀번호

댓글 작성자
 



2012-02-14 11시37분
위의 글에서 "Npgsql2.0.11-bin-ms.net.zip" 파일의 용도를 모르겠다고 했는데... 차이점을 알았습니다. ^^ 그 파일은 순수하게 .NET 2.0 Framework 만 설치된 경우에 사용할 수 있습니다. "2.Npgsql2.0.11-bin-ms.net3.5sp1.zip"에 포함된 Npgsql.dll 은 .NET 3.5 에서만 배포되는 System.Data.Entity.dll 어셈블리를 참조하고 있다는 차이가 있습니다.
정성태
2015-12-01 12시33분
[gwise] 테이블 대소문자 관련 내용이 "PostgreSQL for Data Architects" 책의 210 page에도 나와 있어서 덧글 남기고 갑니다.
테이블 생성할때 대문자나 소문자 하나로 통일하고 쿼리로 사용할때는 대소문자 섞어서 사용해도 됩니다.(이게 좀 귀찮긴 하네요)
닷넷 관련 내용 잘 보고 있습니다.
[guest]
2015-12-01 01시01분
그러게요. 살짝 귀찮긴 하지만 저 정도는 감수해도 무방할 듯 합니다. ^^
정성태
2015-12-01 04시08분
[gwise] GUI툴로 테이블 만들어 내는 쿼리를 보니 대소문자 구분할때는 위에 말씀하신 바와 같이 쌍따옴표가 있습니다.
그러나 쿼리에서 직접 쌍따옴표 없이 대소문자 같이 있는 스크립트로 테이블을 만드니 전부 소문자로 생성이 되네요.
결국 원인은 테이블 생성할때의 차이때문인거 같습니다.

그리고 아래와 같이 두개 테이블 쿼리에서 생성하면 두개 다 생성이 됩니다.
CREATE TABLE Mytb (Id integer ) <- 얘는 실제로는 전부 소문자로 생성됨.
CREATE TABLE "Mytb" ("Id" integer ) <- GUI에서 테이블 생성하면 이렇게 query됨.

Postgresql 테이블이나 컬럼 생성할때 맘편하게 소문자로 하는게 정신건강에 좋을거 같습니다. ^^
[guest]
2021-08-06 09시37분
정성태

... 151  152  153  154  155  156  157  158  159  [160]  161  162  163  164  165  ...
NoWriterDateCnt.TitleFile(s)
1043정성태5/24/201131236.NET Framework: 214. 무료 Linq Provider - DbLinq를 이용한 Firebird 접근파일 다운로드1
1042정성태5/23/201137575개발 환경 구성: 122. PHP 소스를 윈도우 환경에서 빌드하기
1041정성태5/22/201128461.NET Framework: 213. Linq To SQL - ALinq Provider를 이용하여 Firebird 사용파일 다운로드1
1040정성태5/21/201138822개발 환경 구성: 121. .NET 개발자가 처음 설치해 본 Apache + PHP [2]
1039정성태5/17/201131536.NET Framework: 212. Firebird 데이터베이스와 ADO.NET [2]파일 다운로드1
1038정성태5/16/201133478개발 환경 구성: 120. .NET 프로그래머에게도 유용한 Firebird 무료 데이터베이스 [2]
1037정성태5/11/201128326개발 환경 구성: 119. Visual Studio Professional 이하 버전에서도 TFS의 정적 코드 분석 정책 연동이 가능할까? [3]
1036정성태5/7/201194184오류 유형: 121. Access DB에 대한 32bit/64bit OLE DB Provider 관련 오류 [11]
1035정성태5/7/201128856오류 유형: 120. File cannot be opened. Ensure it is a valid Data Link file.
1034정성태5/2/201125907.NET Framework: 211. 파일 잠금 없이 .NET 어셈블리의 버전을 구하는 방법 [2]파일 다운로드1
1033정성태5/1/201131628웹: 19. IIS Express - appcmd.exe를 이용한 applicationHost.config 변경 [2]
1032정성태5/1/201128259웹: 18. IIS Express를 NT 서비스로 변경
1031정성태4/30/201129392웹: 17. IIS Express - "IIS Installed Versions Manager Interface"의 IIISExpressProcessUtility 구하는 방법 [1]파일 다운로드1
1030정성태4/30/201151716개발 환경 구성: 118. IIS Express - localhost 이외의 호스트 이름으로 접근하는 방법 [4]파일 다운로드1
1029정성태4/28/201140841개발 환경 구성: 117. XCopy에서 파일/디렉터리 확인 질문 없애기 [2]
1028정성태4/27/201138228오류 유형: 119. Visual Studio 2010 SP1 설치 후 Windows Phone 개발자 도구로 인한 재설치 문제 [3]
1027정성태4/25/201127404디버깅 기술: 40. 상황별 GetFunctionPointer 반환값 정리 - x86파일 다운로드1
1026정성태4/25/201145658디버깅 기술: 39. DebugDiag 1.1을 사용한 덤프 분석 [7]
1025정성태4/24/201127724개발 환경 구성: 116. IIS 7 관리자 - Active Directory Certification Authority로부터 SSL 사이트 인증서 받는 방법 [2]
1024정성태4/22/201129145오류 유형: 118. Windows 2008 서버에서 Event Viewer / PowerShell 실행 시 비정상 종료되는 문제 [1]
1023정성태4/20/201129988.NET Framework: 210. Windbg 환경에서 확인해 본 .NET 메서드 JIT 컴파일 전과 후 [1]
1022정성태4/19/201125574디버깅 기술: 38. .NET Disassembly 창에서의 F11(Step-into) 키 동작파일 다운로드1
1021정성태4/18/201127824디버깅 기술: 37. .NET 4.0 응용 프로그램의 Main 함수에 BreakPoint 걸기
1020정성태4/18/201128444오류 유형: 117. Failed to find runtime DLL (mscorwks.dll), 0x80004005
1019정성태4/17/201129047디버깅 기술: 36. Visual Studio의 .NET Disassembly 창의 call 호출에 사용되는 주소의 의미는? [1]파일 다운로드1
1018정성태4/16/201132706오류 유형: 116. 윈도우 업데이트 오류 - 0x8020000E
... 151  152  153  154  155  156  157  158  159  [160]  161  162  163  164  165  ...