Jump to content
과거의 기술자료(읽기 전용): https://tech.devgear.co.kr ×
과거의 기술자료(읽기 전용): https://tech.devgear.co.kr

[DocWiki 번역] 캐시된 업데이트 (FireDAC)


Recommended Posts

Docwiki에 있는 "Caching Updates (FireDAC)"를 번역한 글 (번역일: 2022년 3월 12일)


위로 가기: Editing Data (FireDAC)

목차


일반 사항 (Generalities)

캐시된 업데이트 모드에서는 Post / Delete 메소드를 호출하지 않고, 업데이트를 데이터베이스로 포스트(Post)하기를 뒤로 미룬다. 그 결과, 업데이트 여러개를 하나의 묶음으로 포스트(Post)할 수 있고, 원한다면 트랜젝션 하나에 묶어서 보낼 수도 있다.

데이터셋을 캐시된 업데이트 모드로 지정하려면, CachedUpdates 프로퍼티를 True로 지정한다. 그러면 해당 데이터셋은 이 프로퍼티가 마지막으로 True가 된 시점 이후, 또는 마지막으로 CancelUpdates / CommitUpdates 가 호출된 이후에 발생한 모든 변경을 추적한다. 변경 내역은 변경 일지에 포함되며, 여기에는 모든 변경이 발생 시점 순서로 남아있다. FireDAC은 동일 레코드의 여러 버전을 추적하지 않는다. 가장 마지막 변경은 이전 내용을 덮어쓰고, 이전 내용은 업데이트 순서 상 가장 뒤로 옮겨진다.

FireDAC은 "분산형"과 "중앙 집중식" 캐시된 업데이트 모드를 지원한다.

  • 분산형 캐시된 업데이트 모드--각 데이터셋 별로 독립적으로 변경을 추적한다. 고전적 방식이며, 기본 모드이다.
  • 중앙 집중식 캐시된 업데이트 모드--여러 데이터셋들이 변경 로그 하나를 공유하고 변경 내역은 발생 순서대로 기록된다.

 

중앙집중식 캐시된 업데이트 (Centralized Cached Updates)

애플리케이션에서 여러 데이터셋에서 발생된 변경을  발생 순서대로 기록하고 적용하려면 중앙집중식 캐시된 업데이트를 사용한다. 이 목적을 이루려면, TFDSchemaAdapter 인스턴스 하나가 해당 데이터셋들 모두의 SchemaAdapter 프로퍼티에 할당되어야 한다. TFDSchemaAdapter는 여러 데이터셋 안에 있는 모든 로우(Row)와 변경을 담는 중앙 저장소 역할을 한다.

무엇보다, 중앙집중식 캐시된 업데이트는 마스터-디테일 관계에서 유용하다. 마스터 데이터셋의 변경을 디테일 데이터셋으로 전파하기 때문이다. 여기에는 자동-증가 필드 값도 포함된다. 디테일 데이터셋으로 전파하기를 켜러면 FetchOptions.DetailCascade를 반드시 True로 지정한다. 그러면 다음과 같이 작동한다. 

  • 마스터-디테일 변경을 동기화, 그 결과 마스터와 디테일 데이터셋의 변경은 발생 순서 대로 기록되고 적용된다. 예를 들어: 마스터 레코드가 먼저 삽입(Insert)되고 나서 해당 디테일 레코드가 삽입(Insert)된다;
  • 마스터 Identity 컬럼 값을 디테일 데이터셋에 전파한다. 예를 들어, 디테일 데이터셋이 마스터 데이터셋의 Identity 컬럼에 연결되어 있는 레코드에 대해 당신이 업데이트를 반영하면 해당 디테일 레코드는 반드시 마스터 Identity 컬럼의 실제 값을 받아야 한다;
  • 마스터 레코드가 삭제될 때 해당 디테일 레코드도 연쇄적으로 삭제된다. 예를 들어, 마스터 레코드가 삭제되면 해당 디테일 레코드 모두가 삭제되고 변경 로그에 기록된다;
  • 마스터 필드의 변경을 디테일 데이터셋에게 전파한다.

전파되려면 다음 조건이 충족되어야 한다:

DetailServerCascade를 사용하면, FireDAC이 클라이언트 측 연쇄(cascading) 변경을 데이터베이스에 적용할 것인지 말 것인지를 조절할 수 있다. DetailServerCascadee는 FetchOptions.DetailCascade과 함께 사용한다.

중앙집중식 캐시된 업데이트와 전파하기를 켜려면 다음 단계를 진행한다 (먼저, 범위 기반 M/D를 설정하고 CachedUpdates 프로퍼티를 True로 지정한다):

  1. TFDSchemaAdapter를 폼 위에 올려 놓는다.
  2. 마스터 데이터셋의 SchemaAdapter 프로퍼티를 위의 TFDSchemaAdapter로 지정한다.
  3. 디테일 데이터셋의 SchemaAdapter 프로퍼티를 위와 동일한 TFDSchemaAdapter로 지정한다.
  4. 디테일 데이터셋의 FetchOptions.DetailCascade를 True로 지정한다.

위와 같이 하면, 인-메모리 참조 제약이 디테일 데이터셋에 적용된다. 이것은 아래의 SQL 명령과도 유사하다

ALTER TABLE <디테일> ADD CONSTRAINT
FOREIGN KEY (<디테일 필드(들)>)
REFERENCES <master> (<마스터 필드(들)>)
ON DELETE CASCADE
ON UPDATE CASCADE

업데이트를 반영하려면, 애플리케이션에서 데이터셋의 ApplyUpdates 메소드 대신, TFDSchemaAdapter.ApplyUpdates 메소드를 사용해야 한다. 에러를 교정(Reconcile)하려면, 데이터셋의 Reconcile 대신, TFDSchemaAdapter.Reconcile 메소드를 사용한다.

보다 자세한 내용은 중앙집중식 캐시된 업데이트 예제를 본다.

 

업데이트를 추적하기 (Tracking Updates)

애플리케이션이 중앙집중식 캐시된 업데이트 모드에서 작동하고 있으면, 당신은 변경을 추적하고 원한다면 각 데이터셋의 변경을 되돌릴 수도 있다. 변경을 추적하려면 아래에 있는 프로퍼티를 사용한다.

기존 변경을 되돌리려면 아래의 프로퍼티와 메소드를 사용한다.

  • SavePoint – 현재 변경 로그 상태를 설정/획득 한다;
  • RevertRecord – 현재 레코드를 이전 (원래) 상태로 되돌린다;
  • UndoLastChange – 마지막에 변경된 레코드로 가서 그것을 이전 (원래) 상태로 되돌린다;
  • CancelUpdates – 변경 로그 안에 있는 모든 레코드를 되돌린다.

예를 들어, 간단하게 Undo 기능을 구현하려면, actUndo 라는 액션을 하나 만들고 그 액션에 다음과 같이 이벤트 핸들러를 달아준다.

procedure TForm1.actUndoUpdate(Sender: TObject);
begin
  actUndo.Enabled := FDQuery1.UpdatesPending;
end;

procedure TForm1.actUndoExecute(Sender: TObject);
begin
  FDQuery1.UndoLastChange(True);
end;


다른 예로, 인-메모리 트랜젝션을 구현하여 업데이트 묶음 되돌리기를 구현하려면, 다음과 같이 한다.

FDQuery1.CachedUpdates := True;
iSavePoint := FDQuery1.SavePoint;
try
  FDQuery1.Append;
  ...
  FDQuery1.Post;
  FDQuery1.Append;
  ...
  FDQuery1.Post;
  FDQuery1.Append;
  ...
  FDQuery1.Post;
except
  FDQuery.SavePoint := iSavePoint;
end;

주의: 캐시된 업데이트 모드에서는, 다음과 같은 메소드와 프로퍼티가 변경 일지를 사용하여 작동한다.

  • Data 프로퍼티에는 모든 레코드가 들어있다. 심지어 삭제된 것과 업데이트된 사항까지 모두 들어있다.;
  • Delta 프로퍼티는 변경 일지에 담긴 삭제, 삽입, 업데이트된 레코드를 반환한다;
  • CopyRecord, CopyDataSet 메소드는 새 업데이트를 생성하지만 변경 일지는 복사하지 않는다;
  • LoadFromStream, LoadFromFile, SaveToStream, SaveToFile은 데이터를 변경 일지와 함께 불러오거나 저장한다.

캐시된 업데이트 모드에서, 변경 일지에 변경이 남아있을 경우, 일부 메소드와 프로퍼티 설정은 예외를 발생시킨다. 업데이트 사항은 반드시 커밋(Commit) 되거나 취소(Cancel)되어야 한다. 다음과 같은 경우가 여기에 해당된다.

 

업데이트를 반영하기 (Applying Updates)

데이터베이스에 업데이트를 반영하려면, ApplyUpdates 메소드를 사용한다. 만약 업데이트 반영 중인 레코드에서 예외(exception)가 발생되면, 이 예외(exception)는 해당 레코드에 연결된다. ApplyUpdates 메소드에 대해 다음 사항을 알아두자.

  • 예외를 일으키지 않고, 발생된 예외의 갯수를 반환한다;
  • 업데이트들을 묶어서 트랜젝션 하나로 반영하지 않는다. 애플리케이션에서 직접 해야 한다;
  • 즉시 업데이트와 동일한 업데이트 포스트(Post) 로직을 사용한다.

업데이트를 반영한 후에도, 변경된 레코드들은 여전히 변경 로그 안에 남아있다. 변경 로그에서 제거하고, 이 레코드들을 변경되지 않음으로 표시하려면, CommitUpdates 메소드를 호출한다. 예를 들어,

FDQuery1.CachedUpdates := True;
FDQuery1.Append;
...
FDQuery1.Post;
FDQuery1.Append;
...
FDQuery1.Post;
FDQuery1.Append;
...
FDQuery1.Post;
FDConnection1.StartTransaction;
iErrors := FDQuery1.ApplyUpdates;
if iErrors = 0 then begin
  FDQuery1.CommitUpdates;
  FDConnection1.Commit;
end
else
  FDConnection1.Rollback;

주의: 이 경우는 AutoCommitUpdates가 False로 지정된 경우에 해당된다.

  • 만약  AutoCommitUpdates가 True로 지정되면, CommitUpdates를 명시적으로 호출하지 않아도 된다. True로 지정되면, ApplyUpdates를 호출하여 진행된 업데이트에서 성공한 레코드들은 모두 자동으로 변경없음으로 표시되기 때문이다.

 

에러를 검토하기 (Reviewing Errors)

ApplyUpdates 호출 안에서 에러가 발생하면, ApplyUpdates는 해당 에러를 내부 데이터 레코드 구조 안에 기록하고, AMaxErrors 숫자에 도달하기 전까지 업데이트 처리를 지속한다. ApplyUpdates는 예외를 일으키지 않는다. ApplyUpdates 진행 후, 에러가 발생된 레코드를 모두 교정하려면, 교정 처리(reconciling process) 또는 에러가 발생한 레코드 걸러내기를 한다.

레코드를 교정(reconcile)하려면, OnReconcileError 이벤트 핸들러를 할당하고 Reconcile 메소드를 호출한다. OnReconcileError 이벤트 핸들러는 에러를 분석하고 현재 레코드 필드 값을 읽고 변경한다. 빠져나갈 때에는, 액션을 할당하여 FireDAC 코드가 에러와 함께 현재 레코드에 수행할 작업을 지정해야 한다. Reconcile 메소드를 호출한 후에는 ApplyUpdates를 다시 호출하여 에러가 있는 레코드의 변경을 다시 포스트(Post)할 수 있다.

에러가 있는 레코드만 걸러내려면, FilterChangesrtHasErrors를 포함한다. 그후 걸러진 데이터셋을 탐색하고 RowError 프로퍼티를 읽어서 현재 레코드에 연결된 Exception 오브젝트를 얻는다. 예를 들어

var
  oErr: EFDException;
...
if FDQuery1.ApplyUpdates > 0 then begin
  FDQuery1.FilterChanges := [rtModified, rtInserted, rtDeleted, rtHasErrors];
  try
    FDQuery1.First;
    while not FDQuery1.Eof do begin
      oErr := FDQuery1.RowError;
      if oErr <> nil then begin
        // exception 오브젝트 처리
        ...
      end;
      FDQuery1.Next;
    end;
  finally
    FDQuery1.FilterChanges := [rtUnmodified, rtModified, rtInserted];
  end;
end;

 

기타 자료 (See Also)

예제 (Samples)

이 댓글 링크
다른 사이트에 공유하기

이 토의에 참여하세요

지금 바로 의견을 남길 수 있습니다. 그리고 나서 가입해도 됩니다. 이미 회원이라면, 지금 로그인하고 본인 계정으로 의견을 남기세요.

Guest
이 토픽(기고/질문)에 답하기

×   서식있는 텍스트로 붙여넣기.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   이전에 작성한 콘텐츠가 복원되었습니다..   편집창 비우기

×   You cannot paste images directly. Upload or insert images from URL.

 공유하기

×
×
  • Create New...

중요한 정보

이용약관 개인정보보호정책 이용규칙 이 사이트가 더 잘 작동하기 위해 방문자의 컴퓨터에 쿠키가 배치됩니다. 쿠키 설정 변경에서 원하는 설정을 할 수 있습니다. 변경하지 않으면 쿠키를 허용하는 것으로 이해합니다.