본문으로 바로가기

VC++ SQL 접속(윈도우 서비스 프로그램)

category Database/MS-SQL 2017. 10. 20. 12:57

기존에 사용하고 있던 응용프로그램을 윈도우 서비스 프로그램으로 변경하고 나서, 정상적으로 동작 하던 SQL Server 접근에서 오류가 발생했습니다. 결국 문제를 해결했습니다. 간혹 프로젝트를 수행하다 보면 이전에 만들어 놓은 소스를 그냥가져다 사용하면서 비슷한 실수와 시행착오를 종종 격게 되므로 메모를 해 둡니다.
MFC 에서 SQL Server에 접근할 때는 ‘2’ 의 방법을 사용할 것을 권장 합니다. 

1. SQL 에 Local 계정으로 연결하기
‘TestDB’ 데이터베이스의 ‘TestTable’ 테이블을 접근하는 경우의 예제 입니다
Data Source= (서버 이름), Initial Catalog=(DB 이름,또는 스키마) 및 테이블 이름 입니다

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
#include "stdafx.h"
#include
#include
#include 
#import "C:/Program Files/Common Files/System/ado/msado15.dll"  rename( "EOF", "AdoNSEOF" )
using namespace std;
using namespace ADODB;
_bstr_t bstrConnect("Provider='SQLOLEDB'; Data Source='PC001\\SQLEXPRESS'; Initial Catalog='TestDB'; Integrated Security='SSPI';");
int main()
{
    HRESULT hResult = CoInitialize( 0 );
    if( FAILED( hResult ))    {        return hResult;    }
    try
    {
        ADODB::_ConnectionPtr pConnect("ADODB.Connection");
        hResult = pConnect->Open( bstrConnect, "admin", "", ADODB::adConnectUnspecified );
        if (SUCCEEDED(hResult))
        {
            _bstr_t query = "SELECT * FROM TestTable;";
            ADODB::_RecordsetPtr pRecSet( "ADODB.Recordset" );
            hResult = pRecSet->Open( query, _variant_t((IDispatch *) pConnect, true), ADODB::adOpenUnspecified,ADODB::adLockUnspecified, ADODB::adCmdText);
            if( SUCCEEDED( hResult ))
            {
                ADODB::Fields* pFields = NULL;
                hResult = pRecSet->get_Fields( &pFields );               
                while( !pRecSet->AdoNSEOF )
                {
                    for( long lIndex=0; lIndex < pFields->GetCount(); lIndex++ )
                    {
                        
                    }
           pRecSet->MoveNext();
                }
            }
            pRecSet->Close();
            pConnect->Close();
        }
    }
    catch( _com_error& e )
    {
        // Handle Exception
    }
    // Release COM
    CoUninitialize();
    getchar();
    return hResult;
}

2. SQL 에 Server에 연결하기
    아래의 코드에서 특이 점은 Integrated Security=’SSPI’  부분이 없다는 것 입니다.
또 한가지 중요한 점은 윈도우 서비스 프로그램으로 만들어진 이후에도 아래의 접속 방법은 여전히 정상적으로 동작 합니다.

1
2
3
4
5
6
7
8
9
10
11
12
CString szCon;
szCon.Format("Provider=SQLOLEDB; Data Source=%s; Initial Catalog=%s;",szDBServerIP,szDBName);
//szDBName =TestDB(스키마)
//szDBServerIP=IP(IP:port)
CoInitialize(NULL);
m_hresult = m_pConn.CreateInstance((__uuidof(Connection)));
if(FAILED(m_hresult))
{
   CoUninitialize();
   return FALSE;
}
m_hresult = m_pConn->Open(_bstr_t(szCon),szUserID,szUserPW,0);//계정의 ID와 비번을 입력하야한다.

3. SQL 에 Server에 연결하기(Provider=MSDASQL)
아래의 코드는 일반응용 프로그램으로 만들어 졌을 때는 정상적으로 동작 하지만 서비스 프로그램으로 만들어 졌을 때는 정상적으로 동작 하지 않는 코드 입니다.
저는 이문제를 해결하기 위해서 많은 시간을 허비 했습니다. 환경이 바뀌면서 동작이 달라지게 되므로 이런한 코드는 권장할 것이 못됩니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
{
szCon.Format("Provider=MSDASQL.1;persist Security Info=false;User ID=%s;Password=%s;Extended Properties=\"DSN=%s;SERVER=%s;UID=%s;DATABASE=%s;PORT=%s\"",
szUserID,szUserPW,ODBC_DNS,szDBServerIP,szUserID,szDBName,port);
 
CoInitialize(NULL);//Initialize the COM Library
m_hresult = m_pConn.CreateInstance((__uuidof(Connection)));
if(FAILED(m_hresult))
{
printf("Error instantiating Connection object\n");
CoUninitialize();
return FALSE;
}
m_hresult = m_pConn.Open(_bstr_t(szCon),"","",0);