안녕하세요. 델파이 고수님들...
다름 아니라 시스템 개발중 다음과 같은 문제가 있어 큐엔에이에 올려봅니다. 기본적인 흐름은 사용자가 암호를 변경하고자 할때 암호변경화면으로 넘어가고 이상없이 잘 수행하였다면 사용자테이블(사용자, 암호)과 암호변경이력테이블에 관련내용을 저장하는 것입니다.
근데 이상한 것이 서버쪽의 프로시져안에서 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;
우선 서버에 원격호출을 위한 프로시져를 만드셔서 거기서 데이터베이스를 업데이트하시는군요. 별도 함수로 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;