2008/10/13

MFC 에서 간단하게 DAO 사용하기

MFC 프로그래밍에서 간단하게 DAO를 사용하는 코드이다.

예전에는 자주 사용했지만 현재는 로컬데이터베이스 시스템을 이용할 경우에는 MS-Access 보다는 SQLite를 사용한다.

// For Database
#include <atlbase.h>
#include <afxoledb.h>
#include <atlplus.h>
#include <afxdao.h> // For MDB


////////////////////////////////////////////////////////////////////////////
// Header

#pragma once
#pragma warning(disable: 4995)

class CLibDB
{
public:
CLibDB(void);
virtual ~CLibDB(void);

private:
LPCTSTR strBOOL(BOOL bFlag);
CString strVARIANT(const COleVariant& var, char *pBuf = NULL);
void DisplayDaoException(CDaoException* e);
BOOL IsExistentTable(CDaoDatabase *pDatabase, CString strTableName);

public:
CDaoDatabase* m_pDB;
CString m_strDBName;
CString m_strModulePath;

enum ERROR_CODE
{
ERROR_NULL_DB = -100,
ERROR_DB_NOT_OPEN = -101,
ERROR_DB_DATA_NOT_FOUNT = -102,
ERROR_DB_DUP_INDEX_FIDLE = -103,
ERROR_MEMORY_EXCEPTION = -1000
};

int InitDB(void);

int CheckDB(void);
bool CreateDB(CString strDBName);
bool CreateTable(CDaoDatabase* pDB);
};


////////////////////////////////////////////////////////////////////////////
// Source

#include "StdAfx.h"
#include "libdb.h"

CLibDB::CLibDB(void)
{
m_pDB = NULL;

// Get Module Path
m_strModulePath = _T("");

char sfilename[255];
GetModuleFileName(NULL, sfilename, sizeof(sfilename));

char Drive[255];
char Path[255];
char Filename[255];
char Ext[255];
_splitpath(sfilename, Drive, Path, Filename, Ext);

m_strModulePath.Format(_T("%s%s"), Drive, Path);

m_strDBName = m_strModulePath + _T("\MyMDB.mdb");
}

CLibDB::~CLibDB(void)
{
if(m_pDB)
{
if(m_pDB->IsOpen())
m_pDB->Close();
delete m_pDB;
}
}

LPCTSTR CLibDB::strBOOL(BOOL bFlag)
{
return bFlag ? _T("TRUE") : _T("FALSE");
}

CString CLibDB::strVARIANT(const COleVariant& var, char *pBuf /*= NULL*/)
{
CString strRet;
strRet = _T("UNKNOWN");

switch(var.vt){
case VT_EMPTY:
case VT_NULL:
strRet = _T("NULL");
break;
case VT_I2:
strRet.Format(_T("%hd"),V_I2(&var));
break;
case VT_I4:
strRet.Format(_T("%d"),V_I4(&var));
break;
case VT_R4:
strRet.Format(_T("%f"),(double)V_R4(&var));
break;
case VT_R8:
strRet.Format(_T("%f"),V_R8(&var));
break;
case VT_CY:
strRet = COleCurrency(var).Format();
break;
case VT_DATE:
strRet = COleDateTime(var).Format(_T("%m %d %y"));
break;
case VT_BSTR:
strRet = V_BSTRT(&var);
break;
case VT_DISPATCH:
strRet = _T("VT_DISPATCH");
break;
case VT_ERROR:
strRet = _T("VT_ERROR");
break;
case VT_BOOL:
return strBOOL(V_BOOL(&var));
case VT_VARIANT:
strRet = _T("VT_VARIANT");
break;
case VT_UNKNOWN:
strRet = _T("VT_UNKNOWN");
break;
case VT_I1:
strRet = _T("VT_I1");
break;
case VT_UI1:
strRet.Format(_T("0x%02hX"),(unsigned short)V_UI1(&var));
break;
case VT_UI2:
strRet = _T("VT_UI2");
break;
case VT_UI4:
strRet = _T("VT_UI4");
break;
case VT_I8:
strRet = _T("VT_I8");
break;
case VT_UI8:
strRet = _T("VT_UI8");
break;
case VT_INT:
strRet = _T("VT_INT");
break;
case VT_UINT:
strRet = _T("VT_UINT");
break;
case VT_VOID:
strRet = _T("VT_VOID");
break;
case VT_HRESULT:
strRet = _T("VT_HRESULT");
break;
case VT_PTR:
strRet = _T("VT_PTR");
break;
case VT_SAFEARRAY:
strRet = _T("VT_SAFEARRAY");
break;
case VT_CARRAY:
strRet = _T("VT_CARRAY");
break;
case VT_USERDEFINED:
strRet = _T("VT_USERDEFINED");
break;
case VT_LPSTR:
strRet = _T("VT_LPSTR");
break;
case VT_LPWSTR:
strRet = _T("VT_LPWSTR");
break;
case VT_FILETIME:
strRet = _T("VT_FILETIME");
break;
case VT_BLOB:
strRet = _T("VT_BLOB");
break;
case VT_STREAM:
strRet = _T("VT_STREAM");
break;
case VT_STORAGE:
strRet = _T("VT_STORAGE");
break;
case VT_STREAMED_OBJECT:
strRet = _T("VT_STREAMED_OBJECT");
break;
case VT_STORED_OBJECT:
strRet = _T("VT_STORED_OBJECT");
break;
case VT_BLOB_OBJECT:
strRet = _T("VT_BLOB_OBJECT");
break;
case VT_CF:
strRet = _T("VT_CF");
break;
case VT_CLSID:
strRet = _T("VT_CLSID");
break;
}
WORD vt = var.vt;
if(vt & VT_ARRAY){
#pragma warning(disable : 4244)
vt = vt & ~VT_ARRAY;
#pragma warning(default : 4244)
strRet = _T("Array of ");
}
if(vt & VT_BYREF){
#pragma warning(disable : 4244)
vt = vt & ~VT_BYREF;
#pragma warning(default : 4244)
strRet += _T("Pointer to ");
}
if(vt != var.vt){
switch(vt){
case VT_EMPTY:
strRet += _T("VT_EMPTY");
break;
case VT_NULL:
strRet += _T("VT_NULL");
break;
case VT_I2:
strRet += _T("VT_I2");
break;
case VT_I4:
strRet += _T("VT_I4");
break;
case VT_R4:
strRet += _T("VT_R4");
break;
case VT_R8:
strRet += _T("VT_R8");
break;
case VT_CY:
strRet += _T("VT_CY");
break;
case VT_DATE:
strRet += _T("VT_DATE");
break;
case VT_BSTR:
strRet += _T("VT_BSTR");
break;
case VT_DISPATCH:
strRet += _T("VT_DISPATCH");
break;
case VT_ERROR:
strRet += _T("VT_ERROR");
break;
case VT_BOOL:
strRet += _T("VT_BOOL");
break;
case VT_VARIANT:
strRet += _T("VT_VARIANT");
break;
case VT_UNKNOWN:
strRet += _T("VT_UNKNOWN");
break;
case VT_I1:
strRet += _T("VT_I1");
break;
case VT_UI1:
strRet += _T("VT_UI1");
break;
case VT_UI2:
strRet += _T("VT_UI2");
break;
case VT_UI4:
strRet += _T("VT_UI4");
break;
case VT_I8:
strRet += _T("VT_I8");
break;
case VT_UI8:
strRet += _T("VT_UI8");
break;
case VT_INT:
strRet += _T("VT_INT");
break;
case VT_UINT:
strRet += _T("VT_UINT");
break;
case VT_VOID:
strRet += _T("VT_VOID");
break;
case VT_HRESULT:
strRet += _T("VT_HRESULT");
break;
case VT_PTR:
strRet += _T("VT_PTR");
break;
case VT_SAFEARRAY:
strRet += _T("VT_SAFEARRAY");
break;
case VT_CARRAY:
strRet += _T("VT_CARRAY");
break;
case VT_USERDEFINED:
strRet += _T("VT_USERDEFINED");
break;
case VT_LPSTR:
strRet += _T("VT_LPSTR");
break;
case VT_LPWSTR:
strRet += _T("VT_LPWSTR");
break;
case VT_FILETIME:
strRet += _T("VT_FILETIME");
break;
case VT_BLOB:
strRet += _T("VT_BLOB");
break;
case VT_STREAM:
strRet += _T("VT_STREAM");
break;
case VT_STORAGE:
strRet += _T("VT_STORAGE");
break;
case VT_STREAMED_OBJECT:
strRet += _T("VT_STREAMED_OBJECT");
break;
case VT_STORED_OBJECT:
strRet += _T("VT_STORED_OBJECT");
break;
case VT_BLOB_OBJECT:
strRet += _T("VT_BLOB_OBJECT");
break;
case VT_CF:
strRet += _T("VT_CF");
break;
case VT_CLSID:
strRet += _T("VT_CLSID");
break;
}
}

if (pBuf != NULL)
{
int nChar = strRet.GetLength();
#ifdef _UNICODE
WideCharToMultiByte( CP_ACP, 0, strRet, -1,
pBuf, nChar, NULL, NULL );
#else
strcpy(pBuf, (LPCSTR)(LPCTSTR)strRet);
#endif
pBuf[nChar] = '\0';
}

return strRet;
}

void CLibDB::DisplayDaoException(CDaoException* e)
{
CString strMsg;
if (e->m_pErrorInfo != NULL)
{
strMsg.Format(
_T("%s (%d)"),
(LPCTSTR)e->m_pErrorInfo->m_strDescription,
e->m_pErrorInfo->m_lErrorCode);
AfxMessageBox(strMsg);
}
else
{
strMsg.Format(
_T("ERROR:CDaoException\n\n")
_T("SCODE_CODE =%d\n")
_T("SCODE_FACILITY =%d\n")
_T("SCODE_SEVERITY =%d\n")
_T("ResultFromScode =%d\n"),
SCODE_CODE (e->m_scode),
SCODE_FACILITY (e->m_scode),
SCODE_SEVERITY (e->m_scode),
ResultFromScode (e->m_scode));
AfxMessageBox(strMsg);
}
}

BOOL CLibDB::IsExistentTable(CDaoDatabase *pDatabase, CString strTableName)
{
CDaoDatabase *pDB = NULL;
BOOL bDuplicateTableName = TRUE;

if (pDatabase == NULL)
pDB = m_pDB;
else
pDB = pDatabase;

if (pDB == NULL)
return FALSE;

CDaoTableDefInfo tableInfo; // only needed for the call

TRY
{
pDatabase->GetTableDefInfo(strTableName, tableInfo);
}
CATCH (CDaoException, e)
{
if (e->m_pErrorInfo->m_lErrorCode == 3265)
bDuplicateTableName = FALSE;
}
AND_CATCH (CMemoryException, e)
{
// do nothing
;
}
END_CATCH

return bDuplicateTableName;
}

int CLibDB::InitDB()
{
if (m_pDB)
{
if (m_pDB->IsOpen())
m_pDB->Close();

delete m_pDB;
m_pDB = NULL;
}

m_pDB = new CDaoDatabase;

CheckDB();

return 0;
}

int CLibDB::CheckDB(void)
{
CFileStatus fileStatus;

if (CFile::GetStatus( m_strDBName, fileStatus ))
{
CDaoDatabase* pDB = new CDaoDatabase;
CString strQuery;

pDB->Open(m_strDBName);

if (pDB->IsOpen())
{
if (IsExistentTable(pDB, "MYGROUP") == FALSE ||
IsExistentTable(pDB, "MEMBER") == FALSE)
{
AfxMessageBox("Database damaged. Recreate database");
CreateTable(pDB);
}
}

if(pDB)
{
if(pDB->IsOpen())
pDB->Close();
delete pDB;
}
// Find DB File
}
else
{
// DB File Not Found
AfxMessageBox("DB Not Found!!\n\nCreate database.");

CreateDB(m_strDBName);
}


return 0;
}

bool CLibDB::CreateDB(CString strDBName)
{
CDaoDatabase* pDB = new CDaoDatabase;

pDB->Create(strDBName);

if(!pDB)
{
TRACE("Fail to Create Database");
return false;
}
else
{
CreateTable(pDB);

if(pDB->IsOpen())
pDB->Close();
delete pDB;
}

return true;
}

bool CLibDB::CreateTable(CDaoDatabase* pDB)
{
if (!pDB)
return false;

if (!pDB->IsOpen())
return false;

CString strQuery;

TRY {
// Create Comopnent Table
strQuery.Format(
"CREATE TABLE MYGROUP ("
" GROUPID INTEGER PRIMARY KEY"
", ALIAS VARCHAR(50)"
", MEMBERS INTEGER"
")"
);

pDB->Execute(strQuery);
}
CATCH (CDaoException, e)
{
DisplayDaoException(e);
}
END_CATCH


TRY {
// Create Address
CDaoTableDef Table(pDB);
CDaoFieldInfo Field;

Table.Create("MEMBER");

Field.m_strName = "NAME";
Field.m_nType = dbText;
Field.m_lSize = 50;
Field.m_lAttributes = dbVariableField;
Field.m_bRequired = TRUE;
Field.m_bAllowZeroLength = FALSE;
Field.m_lCollatingOrder = dbSortGeneral;
Table.CreateField(Field);

Table.CreateField("GROUPID", dbInteger, 4);
Table.CreateField("NAME", dbText, 80);
Table.CreateField("AGE", dbInteger, 4);
Table.CreateField("HEIGHT", dbSingle, 4);
Table.CreateField("WEIGHT", dbSingle, 4);

Field.m_nType = dbBoolean;
Field.m_lSize = 1;
Field.m_lAttributes = dbFixedField | dbUpdatableField;
Field.m_bRequired = TRUE;
Field.m_bAllowZeroLength = FALSE;
Field.m_strDefaultValue = "1";

Field.m_strName = "Gender";
Table.CreateField(Field);

Field.m_strName = "IsAdult";
Table.CreateField(Field);

Table.Append();
}
CATCH (CDaoException, e)
{
DisplayDaoException(e);
}
END_CATCH

return true;
}

Original Post : http://neodreamer-dev.tistory.com/184

No comments :

Post a Comment