달력

52024  이전 다음

  • 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
트랜잭션 거는 문제 때문에 삽질에 삽질 하다가.. 대충이라도 정리..
참고 페이지

#include <stdlib.h>

CDataSource mDataSource;
CSession mSession;

CDBPropSet DBInit(DBPROPSET_DBINIT);
HRESULT hr;
IString Conn;   // IString 은 그냥 CString / char로 만들어서 쓰면 됨.

  hr = CoInitialize(0);
  if(FAILED(hr))
  {
    AfxMessageBox("CoInitialize 실패");
    return false;
  }

  Conn.Format("PROVIDER=SQLOLEDB;SERVER=[ServerIP | ServerName];UID=[Logid ID];PWD=[PassWord];DATABASE=[DBName]");
  DBInit.AddProperty(DBPROP_INIT_PROMPT, (short)4);

  DBInit.AddProperty(DBPROP_INIT_PROVIDERSTRING, Conn.ToChar());
DBInit.AddProperty(DBPROP_INIT_LCID, (long)1043);

  hr = mDataSource.Open(_T("SQLOLEDB"), &DBInit);
  if(FAILED(hr))
  {
    AddMessage(NSS_E_DB_CONN, "Can't Connect Database");
    return false;
  }

  hr = mSession.Open(mDataSource);
  if(FAILED(hr))
  {
    AddMessage(NSS_E_DB_OPEN_SESSION, "Can't Open Session");
    return false;
  }
//==================================================================================================
// 실제 소스에서 위 / 아래는 각각 함수로 만들어져서 따로 분리 되어 있으나.. 설명을 위해 하나의 소스에 적음
//==================================================================================================
        CCommand<CDynamicAccessor, CRowset, CNoMultipleResults> Cmd;
HRESULT hr;
IString SQLComm, UserID;
int iError;
short sCount;

rReadPacketStream.ReadString(UserID);
sCount = rReadPacketStream.ReadShort();
       mSession.StartTransaction(ISOLATIONLEVEL_READCOMMITTED, 0, NULL, NULL);    // StartTransaction 으로 트랜잭션을 건다.

for(int i = 0; i < sCount; i++)
{
IString Name;
rReadPacketStream.ReadString(Name);

try
{
SQLComm.Format2(1024,"EXEC dbo.BB_SET_ADD_DATA '%s'", Name.ToChar());
hr = Cmd.Open(mSession, SQLComm.ToChar());
if(FAILED(hr))
{
iError = NSS_E_SQL_INSERT;
throw "AddPticher : SQL Insert Failed";
}
}
catch(char *cpErr)
{
mSession.Abort(NULL, FALSE, FALSE);  // sCount 만큼 인서트를 진행하다가.. 한번이라도 오류가 나면 Abort 실행(롤백)
if(strlen(cpErr) > 0) AddMessage(iError, cpErr);
Cmd.Close();
return iError;
}
}
mSession.Commit(FALSE, XACTTC_SYNC, 0);  // 전부 정상적으로 실행 되면 Commit
Cmd.Close();

return true;
}


여기서 중요한건 역시나 StartTransaction , Abort , Commit 

프로시져에는 SET XACT_ABORT ON 을 꼭 적어주자..

Posted by SadDev
|