Q&A

  • 두개의 Table ApplyUpdate 처리가 잘안되요.
안녕하세요. 델파이 고수님들...

다름 아니라 시스템 개발중 다음과 같은 문제가 있어 큐엔에이에 올려봅니다. 기본적인 흐름은 사용자가 암호를 변경하고자 할때 암호변경화면으로 넘어가고 이상없이 잘 수행하였다면 사용자테이블(사용자, 암호)과 암호변경이력테이블에 관련내용을 저장하는 것입니다.

근데 이상한 것이 서버쪽의 프로시져안에서 StartTransaction을 통과하지 못합니다. 물론 암호를 수정하고 작업했는데도 말이죠. 같은 방법으로 델파이4에서 작업해 보았는데 정상수행합니다. 고수님들의 조언 부탁드립니다.



[클라이언트쪽]

function TdmMapscom.fnInsertPasswdChangeTable(sGubun, sSabun, sPasswd: string): Boolean;

var

oUserif, oPasswdChange : OleVariant;

begin

with dmMapscom do begin

try

// Userif Table Open and Update

cdsUserif.Close;

cdsUserif.Params.ParamByName('SABUN').AsString := sSabun;

cdsUserif.Open;



// Passwd 암호화

sPasswd := fnGetEncryption(sPasswd);



cdsUserif.Edit;

cdsUserifPASSWD.Value := sPasswd;

cdsUserifSDATE.Value := fnGetSysDate(gcDateTime);



// Passwdchange Table Insert

if Not cdsPasswdChange.Active then

cdsPasswdChange.Open;



cdsPasswdChange.Append;

cdsPasswdChangeGUBUN.Value := sGubun;

cdsPasswdChangeSABUN.Value := sSabun;

cdsPasswdChangeCHDATE.Value := fnGetSysDate(gcDateTime);

cdsPasswdChangeSTDSOSOK.Value := fnGetStdSosok(sSabun);

cdsPasswdChangePASSWD.Value := sPasswd;

// Passwd 변경자 or Passwd를 초기화 해준사람

cdsPasswdChangeISABUN.Value := gsSabun;



// Master, Detail 처리

cdsUserif.CheckBrowseMode;

cdsPasswdChange.CheckBrowseMode;



if cdsUserif.ChangeCount > 0 then

oUserif := cdsUserif.Delta

else oUserif := Null;



if cdsPasswdChange.ChangeCount > 0 then

oPasswdChange := cdsPasswdChange.Delta

else oPasswdChange := Null;



// 이부분이 서버프로시저 콜하여 처리하는 함수

fnUserifApplyUpdate(oUserif, oPasswdChange); // 서버 프로시저 콜



if VarIsNull(oUserif) and VarIsNull(oPasswdChange) then begin

cdsPasswdChange.Reconcile(oPasswdChange);

cdsUserif.Reconcile(oUserif);

Result := True;

end

else begin

cdsPasswdChange.Reconcile(oPasswdChange);

cdsUserif.Reconcile(oUserif);

Result := False;

end;



cdsUserif.Close;

cdsPasswdChange.Close;

except

fnErrorMsg('데이터베이스에 이상이 있습니다. 시스템 담당자에게 연락주십시오.');

cdsUserif.Close;

cdsPasswdChange.Close;

Result := False;

end;

end;

end;



[Server쪽]

procedure TrdmSecurity.fnUserifApplyUpdate(var oUserif,

oPasswdChange: OleVariant);

var

nErrCount : Integer;

begin

dmMapscom.DBSecu.StartTransaction;

try

if Not VarIsNull(oUserif) then begin

oUserif := dspUserif.ApplyUpdates(oUserif, 0, nErrCount);

if nErrCount > 0 then SysUtils.Abort;

end;

if Not VarIsNull(oPasswdChange) then begin

oPasswdChange := dspPasswdChange.ApplyUpdates(oPasswdChange, 0, nErrCount);

if nErrCount > 0 then SysUtils.Abort;

end;

dmMapscom.DBSecu.Commit;

except

dmMapscom.DBSecu.Rollback;

end;

end;

3  COMMENTS
  • Profile
    hugehead 2000.08.04 00:22
    코드를 보다가 질문이 몇개 생기네요.



    우선 서버에 원격호출을 위한 프로시져를 만드셔서 거기서 데이터베이스를 업데이트하시는군요. 별도 함수로 Delta들을 직접 처리하시는 특별한 이유가 있습니까?



    그리고 그 함수를 호출하기 전에 cdsXXXX.CheckBrowseMode를 실행하시는데...

    그거 문제 있지 않나요? 제가 알기로는 CheckBrowseMode 메소드는 그 Dataset의 현재 State를 확인해서 그것이 Edit나 Insert이면 변경분을 Post해버리는 것으로 알고 있는데요...

    따라서 CheckBrowseMode 호출할때 이미 변경내용을 저장하려 할겁니다.



    그리고, 만약 Userif와 PasswdChangeTable이 마스터 디테일 관계라면, 이렇게 복잡하게 안하고, 간단히 서버에서 Nested Datasets 연결만 잘해주면 Master 테이블의 cds가 알아서 Transaction 관리를 해 줄탠데요...











    > [클라이언트쪽]

    > function TdmMapscom.fnInsertPasswdChangeTable(sGubun, sSabun, sPasswd: string): Boolean;

    > var

    > oUserif, oPasswdChange : OleVariant;

    > begin

    > with dmMapscom do begin

    > try

    > // Userif Table Open and Update

    > cdsUserif.Close;

    > cdsUserif.Params.ParamByName('SABUN').AsString := sSabun;

    > cdsUserif.Open;

    >

    > // Passwd 암호화

    > sPasswd := fnGetEncryption(sPasswd);

    >

    > cdsUserif.Edit;

    > cdsUserifPASSWD.Value := sPasswd;

    > cdsUserifSDATE.Value := fnGetSysDate(gcDateTime);

    >

    > // Passwdchange Table Insert

    > if Not cdsPasswdChange.Active then

    > cdsPasswdChange.Open;

    >

    > cdsPasswdChange.Append;

    > cdsPasswdChangeGUBUN.Value := sGubun;

    > cdsPasswdChangeSABUN.Value := sSabun;

    > cdsPasswdChangeCHDATE.Value := fnGetSysDate(gcDateTime);

    > cdsPasswdChangeSTDSOSOK.Value := fnGetStdSosok(sSabun);

    > cdsPasswdChangePASSWD.Value := sPasswd;

    > // Passwd 변경자 or Passwd를 초기화 해준사람

    > cdsPasswdChangeISABUN.Value := gsSabun;

    >

    > // Master, Detail 처리

    > cdsUserif.CheckBrowseMode;

    > cdsPasswdChange.CheckBrowseMode;

    >

    > if cdsUserif.ChangeCount > 0 then

    > oUserif := cdsUserif.Delta

    > else oUserif := Null;

    >

    > if cdsPasswdChange.ChangeCount > 0 then

    > oPasswdChange := cdsPasswdChange.Delta

    > else oPasswdChange := Null;

    >

    > // 이부분이 서버프로시저 콜하여 처리하는 함수

    > fnUserifApplyUpdate(oUserif, oPasswdChange); // 서버 프로시저 콜

    >

    > if VarIsNull(oUserif) and VarIsNull(oPasswdChange) then begin

    > cdsPasswdChange.Reconcile(oPasswdChange);

    > cdsUserif.Reconcile(oUserif);

    > Result := True;

    > end

    > else begin

    > cdsPasswdChange.Reconcile(oPasswdChange);

    > cdsUserif.Reconcile(oUserif);

    > Result := False;

    > end;

    >

    > cdsUserif.Close;

    > cdsPasswdChange.Close;

    > except

    > fnErrorMsg('데이터베이스에 이상이 있습니다. 시스템 담당자에게 연락주십시오.');

    > cdsUserif.Close;

    > cdsPasswdChange.Close;

    > Result := False;

    > end;

    > end;

    > end;

    >

    > [Server쪽]

    > procedure TrdmSecurity.fnUserifApplyUpdate(var oUserif,

    > oPasswdChange: OleVariant);

    > var

    > nErrCount : Integer;

    > begin

    > dmMapscom.DBSecu.StartTransaction;

    > try

    > if Not VarIsNull(oUserif) then begin

    > oUserif := dspUserif.ApplyUpdates(oUserif, 0, nErrCount);

    > if nErrCount > 0 then SysUtils.Abort;

    > end;

    > if Not VarIsNull(oPasswdChange) then begin

    > oPasswdChange := dspPasswdChange.ApplyUpdates(oPasswdChange, 0, nErrCount);

    > if nErrCount > 0 then SysUtils.Abort;

    > end;

    > dmMapscom.DBSecu.Commit;

    > except

    > dmMapscom.DBSecu.Rollback;

    > end;

    > end;

  • Profile
    전무열 2000.08.04 01:49
    Hugehead님 답변 감사합니다.

    현재 개발중인 시스템이 일반적인 C/S(2-tier)방식이 아니고, 3-Tier방식으로 개발하고 있습니다. 델타를 쓴 이유는 하나의 트랜잭션에서 두개의 테이블을 동시에 업데이트하려고 이 방법을 사용했구요. CheckBrowseMode는 인터넷에서 관련자료를 찾다가 이것을 쓰면 변경된 값을 확실히 가지고 있는다고 해서 사용하고 있습니다.

    그리고 두개의 테이블은 엄밀한 마스터/디테일관계는 아니구요. 단순히 하나의 트랜잭션에서 두개의 테이블을 업데이트하려다 보니 이런 관계가 만들어졌습니다.



    Userif : 개인정보(사원번호, 암호) : 이곳 암호는 항상 최신의 암호임

    : 암호를 변경하므로 이곳은 Update

    PasswdChange : 암호변경내역(사원번호, 변경암호, 변경일자)

    : 변경내역을 입력하므로 이곳은 Insert



    서버쪽에서 에러가 나 좀 무식하게(서버쪽이라 디버깅하기가...쩝...) 군데군데 레벨을 달아 특정값을 찍어 보았는데요. 레벨2 이후부터 아무것도 안찍히고, 질문시에 있었던 클라이언트의 함수부분에서 Exception쪽 처리 "데이터베이스에 이상이 생겼습니다. 담당자에게 연락바랍니다."라는 메시지박스가 떠오릅니다.



    [Server쪽]

    procedure TrdmSecurity.fnUserifApplyUpdate(var oUserif,

    oPasswdChange: OleVariant);

    var

    nErrCount : Integer;

    begin

    // 레벨1 설치

    dmMapscom.DBSecu.StartTransaction;

    // 레벨2 설치(유독 이 부분 레벨이 안찍힘)

    try

    if Not VarIsNull(oUserif) then begin

    // DataSetProvider(Userif) ApplyUpdate

    oUserif := dspUserif.ApplyUpdates(oUserif, 0, nErrCount);

    // 레벨3 설치

    if nErrCount > 0 then SysUtils.Abort;

    end;

    if Not VarIsNull(oPasswdChange) then begin

    // DataSetProvider(passwdChange) ApplyUpdate

    oPasswdChange := dspPasswdChange.ApplyUpdates(oPasswdChange, 0, nErrCount);

    // 레벨4 설치

    if nErrCount > 0 then SysUtils.Abort;

    end;

    dmMapscom.DBSecu.Commit;

    except

    dmMapscom.DBSecu.Rollback;

    end;

    end;



    혹시나 해서 CheckBrowseMode를 막고 다시 해봤는데요. 똑같습니다.



    그래도 항상 고수님들의 성실한 답변 감사합니다.



  • Profile
    hugehead 2000.08.04 02:22
    저도 역시 3-tier로 Midas를 이용한 프로젝트 개발 중입니다.



    전무열님과 비슷한 경우를 겪어 봤습니다.



    즉 한번에 두개의 테이블을 건드리는 것 말이죠.

    혹시 서버쪽에 BDE를 사용하십니까, 아니면 ADO를 사용하십니까?



    아뭏든간에, 그런 경우에 제가 borland의 뉴스그룹을 뒤지다 보니까 여러 자료를 접하게