2010년 2월 9일 화요일

[Tips]Scoping cursors to edit operations

이 문서는 ArcGIS 9.3. 버전을 기준으로 작성되었으며, .NET C#(3.0) 샘플 코드 실행을 위해서는 다음의 어셈블리를 참조해야 한다.
- ESRI.ArcGIS.ADF
- ESRI.ArcGIS.Geodatabase
- ESRI.ArcGIS.System (ESRI.ArcGIS.esriSystem)

이 문서는 Geodatabase API를 사용하는 개발자들에게 CheatSheet(커닝페이퍼?)을 제공할 목적으로 작성되었으며 주요 내용은 성능향상, 범하기 쉬운 실수 등을 제공한다.
예제 코드는 특정 상황에 대한 샘플 코드로서 패턴을 제공하고, 상황에 따라 오류를 비교하기 위해 임의의 오류를 포함하고 있으므로 이 코드를 재활용해서는 안된다.

④ Scoping cursors to edit operations 
버전 데이터셋(versioned dataset)으로부터 커서를 생성할 때, 생성된 커서는 지오데이터베이스의 특정 상태에 의존한다.

예를 들어 만약 지오데이터베이스의 상태가 변경되고, 현재 편집 작업의 커밋/취소 후 새로운 편집작업이 시작된다면:
 - 이 커서는 더이상 유효하지(Valid)않고 사용되어서는 안된다.
 - 부적절한 상태에서 커서에 대한 편집을 수행할 경우 데이터 손상이나 얘기치 않은 동작이 발생할 수 있다.
 
다음 코드는 피해야 할 예제이다. 하나의 편집작업 내에 같은 커서를 생성 후 다음 편집작업에 Insert 작업을 수행한다.

[code c#]
public static void IncorrectCursorScoping(IWorkspace workspace, IFeatureClass  featureClass)
{
  // Start an edit session and edit operation.
  using(ComReleaser comReleaser = new ComReleaser())
  {
    IWorkspaceEdit workspaceEdit = (IWorkspaceEdit)workspace;
    workspaceEdit.StartEditing(true);
    workspaceEdit.StartEditOperation();

    // Create a new insert cursor and feature buffer.
    IFeatureCursor featureCursor = featureClass.Insert(true);
    comReleaser.ManageLifetime(featureCursor);

    IFeatureBuffer featureBuffer = featureClass.CreateFeatureBuffer();
    comReleaser.ManageLifetime(featureBuffer);

    // Insert a feature.
    featureBuffer.Shape = new PointClass
    {
      X = 5, Y = 10
    };
    featureCursor.InsertFeature(featureBuffer);

    // Abort the edit operation and start a new one.
    workspaceEdit.AbortEditOperation();
    workspaceEdit.StartEditOperation();

    // Insert another feature.
    featureBuffer.Shape = new PointClass
    {
      X = 10, Y = 5
    };
    featureCursor.InsertFeature(featureBuffer);

    // Commit the edit operation and stop editing.
    workspaceEdit.StopEditOperation();
    workspaceEdit.StopEditing(true);
  }
}
[/code]
위에서 사용된 코드 패턴을 사용하는 대신 편집작업마다 새로운 커서를 사용해야 한다.
이런 종류의 패턴에 있어서 ComReleaser를 이용한 using 블록을 이용하여 Lifetime을 관리하는 것이 좋다.

[code c#]
public static void CorrectCursorScoping(IWorkspace workspace, IFeatureClass featureClass)
{
  // Start an edit session and edit operation.
  IWorkspaceEdit workspaceEdit = (IWorkspaceEdit)workspace;
  workspaceEdit.StartEditing(true);
  workspaceEdit.StartEditOperation();

  // Create a new insert cursor and feature buffer.
  using(ComReleaser comReleaser = new ComReleaser())
  {
    IFeatureCursor featureCursor = featureClass.Insert(true);
    comReleaser.ManageLifetime(featureCursor);

    IFeatureBuffer featureBuffer = featureClass.CreateFeatureBuffer();
    comReleaser.ManageLifetime(featureBuffer);

    // Insert a feature.
    featureBuffer.Shape = new PointClass
    {
      X = 5, Y = 10
    };
    featureCursor.InsertFeature(featureBuffer);
  }

  // Abort the edit operation and start a new one.
  workspaceEdit.AbortEditOperation();
  workspaceEdit.StartEditOperation();

  // Create another insert cursor and feature buffer.
  using(ComReleaser comReleaser = new ComReleaser())
  {
    IFeatureCursor featureCursor = featureClass.Insert(true);
    comReleaser.ManageLifetime(featureCursor);

    IFeatureBuffer featureBuffer = featureClass.CreateFeatureBuffer();
    comReleaser.ManageLifetime(featureBuffer);

    // Insert another feature.
    featureBuffer.Shape = new PointClass
    {
      X = 10, Y = 5
    };
    featureCursor.InsertFeature(featureBuffer);
  }

  // Commit the edit operation and stop editing.
  workspaceEdit.StopEditOperation();
  workspaceEdit.StopEditing(true);
}
[/code]
출처 : ArcGIS Resource Center