首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> VC >> 關於VC++

ODBC 完善資料庫程式補充:動態建立系統 DSN 完整實作與 CString 陷阱

     編輯:關於VC++

背景

原文《一個完善的 ODBC 數據庫程序》讀者建議:**程式應自動建立 DSN**,避免使用者手動設定。作者採納並實作於 `CMainFrame::OnCreate`。

完整實作代碼

int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct) {
    if (CFrameWnd::OnCreate(lpCreateStruct) == -1) return -1;
    
    // 1. 取得專案根目錄下的 student.mdb 路徑
    CString sPath;
    GetModuleFileName(NULL, sPath.GetBufferSetLength(MAX_PATH+1), MAX_PATH);
    sPath.ReleaseBuffer();
    int nPos = sPath.ReverseFind('\\'); sPath = sPath.Left(nPos);
    CString lpszFile = sPath + _T("\\student.mdb");
    
    // 2. 組裝 SQLConfigDataSource 參數字串
    // 注意:參數以 '\0' 分隔,結尾雙 '\0\0'
    char* szDesc = new char[256];
    sprintf(szDesc, "DSN=%s? DESCRIPTION=TOC support source? DBQ=%s? FIL=MicrosoftAccess? DEFAULTDIR=%s??",
            "not", lpszFile, sPath); // "not" 為 DSN 名稱
    
    // 3. 將 '?' 替換為 '\0'
    int mlen = strlen(szDesc);
    for (int i=0; i<mlen; i++)
        if (szDesc[i] == '?') szDesc[i] = '\0';
    
    // 4. 呼叫 API 建立系統 DSN
    #include <odbcinst.h> // 必須包含
    if (FALSE == SQLConfigDataSource(NULL, ODBC_ADD_SYS_DSN,
            "Microsoft Access Driver (*.mdb)\0", (LPCSTR)szDesc))
        AfxMessageBox(_T("建立 DSN 失敗"));
    
    delete[] szDesc;
    return 0;
}

兩大關鍵陷阱

陷阱說明解法
CString 內含 '\0' 截斷`CString` 以第一個 '\0' 為結尾,無法直接傳遞多段參數使用 `char*` 緩衝區組裝,再手動將分隔符 '?' 替換為 '\0'
遺漏 odbcinst.h未包含標頭導致 `SQLConfigDataSource` 未宣告`#include ` 並連結 `odbccp32.lib`

進階應用:使用者自訂 DSN 名稱與資料庫路徑

// 對話框輸入 DSN 名稱、瀏覽選擇 .mdb
CString dsnName, mdbPath;
// ... 取得使用者輸入 ...

char* szDesc = new char[512];
sprintf(szDesc, "DSN=%s? DESCRIPTION=Auto DSN? DBQ=%s? FIL=MicrosoftAccess? DEFAULTDIR=%s??",
        dsnName, mdbPath, mdbPath.Left(mdbPath.ReverseFind('\\')));
int len = strlen(szDesc);
for (int i=0; i<len; i++) if (szDesc[i]=='?') szDesc[i]='\0';

SQLConfigDataSource(NULL, ODBC_ADD_SYS_DSN,
    "Microsoft Access Driver (*.mdb)\0", (LPCSTR)szDesc);
delete[] szDesc;

同理可用 `ODBC_REMOVE_SYS_DSN` 移除、`ODBC_CONFIG_SYS_DSN` 修改。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved