{{div_begin}} [[← 9 章に戻る|Introduction to Conduit Development601/9]] [[↑トップへ|Introduction to Conduit Development601]] [[付録 A に進む →|Introduction to Conduit Development601/A]] {{div_end}} {{div_begin style="margin-bottom:-10px"}} !!!10 コンジットの開発 {{div_end}} {{div_begin "style='position:absolute;right:0px;font-size:70%;margin-right:15px;margin-top:15px;width:250px;'"}} *{{goto Chooseing a Starting Point,開始点の選択}} **{{goto First Decisions,最初の決定}} **{{goto Comparing Key Features,キーとなる機能の比較}} *{{goto Generic Conduit Framework,Generic Conduit Framework}} *{{goto Classic Sync Manager API,クラシック同期マネージャ API}} **{{goto Registering Your Conduit with Sync Manager,コンジットの同期マネージャへの登録}} **{{goto Opening Your Database,データベースのオープン}} **{{goto Working with Databases,データベースへの動作}} **{{goto Deleting Records in Handheld Databases,ハンドヘルド データベースの中のレコードの削除}} **{{goto Cleaning Up Records,レコードのクリーン アップ}} **{{goto Closing Your Database,データベースのクローズ}} {{div_end}} {{div_begin "style='position:relative;padding:0px;padding-right:5px;padding-left:10px;margin-right:250px;margin-top:20px;width:auto;border-right-style:dotted;border-right-width:2px;border-right-color:silver;'"}} この章では、作成するコンジットの必要条件に最も適した開発アプローチはどれか、そして使用可能な CDK スイートのどれがそのアプローチをサポートするかを決定するための基礎知識を提供します。 この章には以下の節があります。 *{{goto Chooseing a Starting Point,開始点の選択}} *{{goto Generic Conduit Framework,Generic Conduit Framework}} *{{goto Classic Sync Manager API,クラシック同期マネージャ API}} !!{{anchor Chooseing a Starting Point}}開始点の選択 {{goto top,^TOP^}} この節では、あなたが最初にする必要がある決定を示し、それから CDK の Sync Suite の機能比較を提供します。 *{{goto First Decisions,最初の決定}} *{{goto Comparing Key Features,キーとなる機能の比較}} !{{anchor First Decisions}}最初の決定 {{goto top,^TOP^}} ここでは、どの Sync Suite があなたのニーズに最も適合するかを決定するときに考慮すべき問題を示します: *1. '''低レベル インターフェイス、Generic Conduit Framework のどちらを使用するか選択します。'''{{goto Table 10.2,表 10.2}} が示すように、C/C++ Sync Suite は Generic Conduit Framework の実装を提供します; すべてのスイートは、C-ベース同期マネージャ API と直接的、間接的に対応するより低いレベルのインターフェイスを提供します。{{br}}あなたの設計要求に基づき、これらの開始点を比較するための助けとして {{goto Table 10.1,表 10.1}} を使用してください。 {{anchor Table 10.1}} '''表 10.1 Generic Conduit Framework と低レベル API の比較''' ,コンジット設計要求,"低レベル同期マネージャ API {{fn すべてのスイートで低レベル インターフェイスは使用可能です。C/C++ Sync Suite では、コンジットは同期マネージャに直接アクセスすることができます。COM Sync Suite では、コンジットは COM 同期モジュールを経由して間接的に同期マネージャにアクセスすることができます。}}","Generic Conduit Framework {{fn C/C++ Sync Suite で使用可能です。}}" ,"標準データ ソース(ACCESS, ODBC, CSV など)へのインターフェイス",,最適 ,MFC-ベース アプリケーション,,適 ,プラットフォームをまたがるソース コード,,最適 ,素早い試作アプリケーション開発,適,"適(コンジット ウィザード {{fn C/C++ Sync Suite でのみ使用可能です。}} を使用します)" ,データのアップロード/ダウンロード,最適,適 ,オンライン/オフライン トランザクション処理,最適, {{footnote_list}} *2. '''スイートを選択します。'''{{goto Table 10.2,表 10.2}} は、CDK の同期スイートの高レベル比較を提供しています。どれがあなたの必要性に最も良く適合するかを決定するための助けとして、この表と各スイートに添付されている ''Companion'' ドキュメントを使用してください({{goto Related Documentaion,「関連文書」|Introduction to Conduit Development601/0}} を参照してください)。{{br}}それぞれのスイートの主な利点は: **C/C++ Sync Suite はすべての機能のスーパーセットを提供するので、ある開発者はそれを使用してすべての要求を満たすことになります。 **COM Sync Suite は、あなたが COM を使用可能な言語 - Visual Basic のような手続き型言語を含む - のいずれかでコンジットを開発することを可能にします。COM Sync Suite はあなたのコンジットが基本的な C API のいくつかにアクセスするための単純な COM インターフェイスを提供します。 !{{anchor Comparing Key Features}}キーとなる機能の比較 {{goto top,^TOP^}} {{goto Table 10.2,表 10.2}} は各同期スイートのキーとなる機能を比較しています。この表は CDK 機能の包括的なリストではありません。各スイートについて更に学ぶには、{{goto Related Documentation,「関連文書」|Introduction to Conduit Development601/0}} を参照してください。 {{goto Table 10.2,表 10.2}} は以下の機能を比較しています: *'''サポートされるデスクトップ機能''' は、各同期スイートの API 経由で使用可能な機能をリスト アップしています。言及されている他の機能は、デスクトップ アプリケーション、コンジットとハンドヘルド アプリケーション インストーラを開発するために重要です。 *'''サポートされる IDE と開発プラットフォーム''' は、PalmSource 社が各スイートでサポートする統合開発環境をリスト アップしています。 *'''サポートされる使用プラットフォーム''' は、PalmSource 社がコンジットの使用をサポートするプラットフォームをリスト アップしています。 {{anchor Table 10.2}} '''表 10.2 CDK同期スイートの機能比較''' ,スイート,COM Sync Suite,C/C++ Sync Suite ,'''サポートされるデスクトップ機能''',, ,ユーザ データ(またはユーザ マネージャ)API - HotSync マネージャ ユーザとハンドヘルドの拡張カードについての情報にアクセスするためのもの,Yes,Yes ,コンジット マネージャ - コンジットを HotSync マネージャに登録するインストーラのためのもの,Yes,Yes ,通知機能 DLL - デスクトップ アプリケーションに HotSync 実施が開始/停止したことを通知するためのもの,No,Yes ,通知機能インストール マネージャ - 通知機能を HotSync マネージャに登録するインストーラのためのもの,Yes,Yes ,インストール コンジット マネージャ - インストール コンジットを HotSync マネージャに登録するインストーラのためのもの,Yes,Yes ,インストール援助機能 - アプリケーションをハンドヘルドの主記憶装置にインストールする、または、ファイルを拡張カードにインストールするインストーラのためのもの,Yes,Yes ,'''サポートされる IDE と開発プラットフォーム''',, ,"Microsoft Visual Studio .NET (Visual C++ と Visual Basic) 2003 {{fn Visual Studio .NET 2002 と Visual Basic 6 が機能することは実証されてきました。しかし、公式にはサポートされません。}}:{{br}}Windows 2000 と XP",Yes,Yes ,'''サポートされる使用プラットフォーム''',, ,"Windows 98SE, ME, 2000, XP",Yes,Yes ,'''その他''',, ,プロジェクトと開始コードを自動的に生成するウィザード,No,Yes {{footnote_list}} !!{{anchor Generic Conduit Framework}}Generic Conduit Framework {{goto top,^TOP^}} Generic Conduit Framework を使ってコンジットを作成するということは、ある特定のクラスを引き出してきて、それらをあなたがハンドヘルドまたはデスクトップ コンピュータで使用したいデータ フォーマットに合わせてカスタマイズするということです。 {{goto Figure 10.1,図 10.1}} は、Generic Conduit Framework の構造を描いています。これらのクラス名は C++ Generic Conduit クラス名です。他のスイートの Generic Conduit の構造を知りたければ、{{goto Related Documentaion,「関連文書」|Introduction to Conduit Development601/0}} で説明されている各スイートのためのドキュメントを参照してください。 {{anchor Figure 10.1}} '''図 10.1 Generic Conduit Framework''' {{img intro_conddevelopmenta.gif,style='width:624px;height:330px;'}} Generic Conduit Framework は以下のベース クラスから成り立ちます: *'''カテゴリ''' クラスは、標準 Palm OS カテゴリ データにアクセスし、管理します。 *'''レコード''' クラスは、レコードをハンドヘルドでのフォーマットとデスクトップ コンピュータでのフォーマット間で変換します。 *'''同期ロジック''' クラスは、以下のグループに分けられます: **'''データベース マネージャ''' クラスは、ハンドヘルドまたはデスクトップ コンピュータからのレコードを保存、取得します。 **'''同期機能'''クラスは、ハンドヘルドのデータベースからのレコードとアプリケーション情報ブロックの同期をとります。コアの同期ロジックはこれらのクラスの中に実装されます。 *'''ログ''' クラスは、診断情報を HotSync マネージャによって維持されるログ ファイルに書き出すために使用されます。 以下のステップは、Generic Conduit Framwork をベースにするコンジットをどのように実装し、それをどのようにあなたのレコード フォーマットに適合するようにカスタマイズするのかを要約しています。 *Step 1: あなたのレコード フォーマットを記述します。 *Step 2: あなたのレコードの保存と取得を実装します。 *Step 3: バックアップ データベースまたはアーカイブ データベースの保存と取得を実装します。 *Step 4: Generic {{span style='color:blue;font-family:monospace;',CPalmRecord}} フォーマットとのレコードの変換を実装します。 *Step 5: {{span style='color:blue;font-family:monospace;',AppInfo}} データの同期を実装します。 これらの基本ステップはすべてのスイートで同じです。しかし、厳密な実装方法はさまざまです。更なる情報は、各スイートのドキュメントを参照してください。 以下のステップは、HotSync マネージャが Generic Conduit Framework をベースにしたコンジットに制御を渡すときの一般的な同期実施の基本的な制御フローの概要です: +HotSync マネージャはあなたの {{span style='color:blue;font-family:monospace;',OpenConduit()}} 関数(他のスイートでは、あなたの同期処理を開始するメソッド)を呼び出します。呼び出された関数は、渡された同期プロパティを検証して同期のタイプ(高速同期または低速同期)を決定しなければなりません。 +あなたの {{span style='color:blue;font-family:monospace;',OpenConduit()}} 関数は {{span style='color:blue;font-family:monospace;',CSynchronizer}} オブジェクトをインスタンス化して以下のタスクを実行します: ++コンジットを登録します(C API-ベース コンジットでのみ)。 ++渡された同期プロパティを検証して同期のタイプを決定します。一般には高速同期か低速同期です。 ++データベース マネージャ オブジェクト(ハンドヘルド、デスクトップ、アーカイブ、バックアップ)を作成します。 ++提供される同期ロジックを使ってカテゴリ情報の同期をとります。 ++高速同期、低速同期、ハンドヘルドがデスクトップを上書き、デスクトップがハンドヘルドを上書き、何もしないを使用してレコードの同期をとります。 ++マネージャ オブジェクトを削除します。 ++結果を HotSync ログに書き込みます。 実行フローを追っていくために各スイートで提供されるサンプル コンジットを参照してください。 !!{{anchor Classic Sync Manager API}}クラシック同期マネージャ API {{goto top,^TOP^}} この節では、一般的なコンジットから C/C++ Sync Suite のクラシック同期マネージャへの呼び出しフローについて説明します。これらの基本的なコンセプトはすべてのスイートで同じです。しかし、厳密な実装方法はさまざまです。更なる情報は、{{goto Related Documentaion,「関連文書」|Introduction to Conduit Development601/0}} で説明されている各スイートのドキュメントを参照してください。 クラシック同期マネージャへの呼び出しは以下のカテゴリに分類されます: *コンジットの登録(C API-ベース コンジットでのみ)。 *データベースのオープン。 *レコードの読み込み、書き込み。 *レコード カテゴリに対する動作。 *データベースのクローズ。 *コンジットのアンインストール。 この節の中のコードの断片は、C/C++ Sync Suite で書かれたサンプル コンジットがどのようにクラシック同期マネージャ呼び出しを使用するのかを簡潔に示すのを手助けします。使用方法と主要なステップは他のスイートでも類似です。 !{{anchor Registering Your Conduit with Sync Manager}}コンジットの同期マネージャへの登録 {{goto top,^TOP^}} あなたは、{{goto SyncRegisterConduit,SyncRegisterConduit()|C/C++ Sync Suite Reference601/5}} 関数を呼び出すことによって、あなたのコンジットを同期マネージャに登録しなければなりません同期マネージャはあなたのコンジットのハンドルを返してきて、あなたはそれをその後に続く呼び出しの中で使用します。あなたのコンジットが完了したとき、あなたは、{{goto SyncUnRegisterConduit,SyncUnRegisterConduit()|C/C++ Sync Suite Reference601/5}} 関数を呼び出すことによって、コンジットを登録解除します。たいていのコンジットはこれらの呼び出しを自身の {{goto OpenConduit,OpenConduit()|C/C++ Sync Suite Reference601/6}} 関数の中に作成します。 ---- '''NOTE:'''同期マネージャへの登録と HotSync マネージャへの登録を混同しないように注意してください。あなたのコンジットは実行時に同期マネージャに登録されなければなりません。あなたはあなたのコンジットをインストール時に HotSync マネージャに登録しなければなりません。さもなければ、HotSync マネーははあなたのコンジットを実行しません(各スイートの ''Dompanion Document'' の「インストーラの作成」を参照してください)。 ---- !{{anchor Opening Your Database}}データベースのオープン {{goto top,^TOP^}} あなたは {{goto SyncCreateDB,SyncCreateDB()|C/C++ Sync Suite Reference601/4-1}} 関数を使ってハンドヘルド上に新しいオープンされたデータベースを作成することができます。また、{{goto SyncOpenDB,SyncOpenDB()|C/C++ Sync Suite Reference601/4-1}} 関数を使って存在するハンドヘルド データベースをオープンすることができます。{{goto Listing 10.1,コード 10.1}} は、見本の {{span style='color:blue;font-family:monospace;',OpenDataBase()}} 関数からのコードを示しています。この関数は {{span style='color:blue;font-family:monospace;',SyncCreateDB()}} 関数と {{span style='color:blue;font-family:monospace;',SyncOpenDB()}} 関数の両方を呼び出しています。 {{anchor Listing 10.1}} '''コード 10.1 ハンドヘルド データベースのオープン''' BOOL OpenDataBase( CLogMgr& theLog, const char * pName, DWORD dbCreator, DWORD dbType, BYTE& hDataBase, WORD& dbRecordCount, BOOL clearDB ) { long retVal; // Open the remote database. retVal = SyncOpenDB( pName, 0, hDataBase ); if ( retVal ) { if ( retVal == SYNCERR_FILE_NOT_FOUND ) { TRACE( "SyncOpenDB( %s ) failed [ %lX ], attempting to create DB.\n", pName, retVal ); // The database does not exist, so create it. CDbCreateDB createInfo; memset( &createInfo, 0, sizeof( CDbCreateDB ) ) ; createInfo.m_Creator = dbCreator; createInfo.m_Type = dbType; createInfo.m_Flags = eRecord; // eRecord; createInfo.m_CardNo = 0; // Target card number createInfo.m_Version = 0; ASSERT( strlen( pName ) <= DB_NAMELEN ); strcpy( createInfo.m_Name, pName ); retVal = SyncCreateDB( createInfo ); if ( retVal ) { CString theDBName( pName ); // fatal error theLog.Message( IDS_CANT_CREATE_DB, theDBName, TRUE ); TRACE( "SyncCreateDB( %s ) failed [ %lX ].\n", pName, retVal ); return FALSE; } else { // Database is open with handle createInfo.m_FileHandle. hDataBase = createInfo.m_FileHandle; TRACE( "SyncCreateDB( %s ) succeeded.\n", pName ); } } else { CString theDBName( pName ); // fatal error theLog.Message( IDS_CANT_OPEN_DB, theDBName, TRUE ); TRACE( "SyncOpenDB( %s ) failed [ %lX ].\n", pName, retVal ); return FALSE; } } // If clearDB, then clear all the existing records in the database. if ( clearDB ) { retVal = SyncPurgeAllRecs( hDataBase ); if ( retVal ) { CString theDBName( pName ); // fatal error theLog.Message( IDS_CANT_PURGE_DB, theDBName, TRUE ); TRACE( "SyncPurgeAllRecs( %s ) failed [ %lX ].\n", pName, retVal ); return FALSE; } else { TRACE( "SyncPurgeAllRecs( %s ) succeeded.\n", pName ); } } // Determine how many records are in the remote database. retVal = SyncGetDBRecordCount( hDataBase, dbRecordCount ); if ( retVal ) { if ( hDataBase ) SyncCloseDB( hDataBase ); CString theDBName( pName ); // fatal error theLog.Message( IDS_CANT_GET_DBRECCOUNT, theDBName, TRUE ); TRACE( "SyncGetDBRecordCount( %s ) failed [ %lX ].\n", pName, retVal ); return FALSE; } return TRUE; } // OpenDataBase !{{anchor Working with Databases}}データベースへの動作 {{goto top,^TOP^}} 各データベースはいかの特性を持つレコードの集まりです: *データベースの中の各レコードは、そのデータベースの中で固有の ID を持ちます。 *データベースの中の各レコードは、そのレコードがプライベートである、削除された、変更された、アーカイブされた、Busy 状態であるというマークを付けられているかどうかを示すフラグを持ちます。 *データベースの中の各レコードは、カテゴリに属します。 *データベースはデータベースについてのグローバル情報を保存するアプリケーション情報ブロックを保持します。このブロックは通常、データベースの中のレコードのカテゴリ名を保存するために使用されます。 *データベースはデータベースの中のレコードの順序情報を保存するソート情報ブロックを保持します。このブロックはアプリケーションによって使用されます; Palm OS はそれを使用しません。 {{anchor Reading Records from a Handheld Database}} '''ハンドヘルド データベースからのレコードの読み込み''' {{goto Table 10.3,表 10.3}} の中で示されているように同期マネージャはハンドヘルド上のデータベースからレコードとリソースを取得するためのいくつかの関数を提供します。これらの関数はそれぞれレコードまたはリソースを {{goto CRawRecordInfo,CRawRecordInfo|C/C++ Sync Suite Reference601/4-1}} クラスのオブジェクトに読み込みます。 あなたは、各関数を呼び出す前に、ある特定の未加工レコード オブジェクト フィールドに情報を詰めなければなりません。関数はハンドヘルドからレコードを取得し、他のフィールドにレコード情報を詰め込みます。各関数のために要求されるフィールドは、各関数のためのドキュメントの中で説明されます。 {{anchor Table 10.3}} '''表 10.3 ハンドヘルド データベースからレコードを読み込むための関数''' ,関数,説明 ,"{{goto SyncReadNextModifiedRec,SyncReadNextModifiedRec|C/C++ Sync Suite Reference601/4-2}}",ハンドヘルド上のオープンされたレコード データベースから次の変更された、アーカイブされた、削除されたレコードを取得する反復関数。 ,"{{goto SyncReadNextModifiedRecInCategory,SyncReadNextModifiedRecInCategory|C/C++ Sync Suite Reference601/4-2}}",ハンドヘルド上のオープンされたデータベースから、あるカテゴリの中にある変更されたレコード - 削除されたレコードとアーカイブされたレコードを含む - を取得する反復関数。 ,"{{goto SyncReadNextRecInCategory,SyncReadNextRecInCategory|C/C++ Sync Suite Reference601/4-2}}",ハンドヘルド上のオープンされたデータベースから、あるカテゴリの中にあるすべてのレコード - 削除されたレコード、アーカイブされたレコード、変更されたレコードを含む - を取得する反復関数。 ,"{{goto SyncReadRecordById,SyncReadRecordById|C/C++ Sync Suite Reference601/4-2}}",ハンドヘルド上のオープンされたデータベースから、ID によって、レコードを取得します。 ,"{{goto SyncReadRecordByIndex,SyncReadRecordByIndex|C/C++ Sync Suite Reference601/4-2}}",ハンドヘルド上のオープンされたデータベースから、インデックスによって、レコードを取得します。 ,"{{goto SyncReadResRecordByIndex,SyncReadResRecordByIndex|C/C++ Sync Suite Reference601/4-2}}",ハンドヘルド上のオープンされたリソース データベースから、インデックスによって、リソース レコードを取得します。 {{goto Listing 10.2,コード 10.2}} は、インデックスによってレコードを読み込むために {{span style='color:blue;font-family:monospace;',SyncReadRecordByIndex()}} を呼び出す見本の {{span style='color:blue;font-family:monospace;',ImportPrefs()}} メソッドを示しています。 {{anchor Listing 10.2}} '''コード 10.2 ハンドヘルド データベースからのレコードの読み込み''' BOOL CNetPrefs::ImportPrefs( BYTE hHHDataBase, WORD recIndex ) { BYTE readBuf[ READ_BUF_SIZE ]; BOOL importSuccess = TRUE; fHDataBase = hHHDataBase; // Read from the HH database at index recIndex. CRawRecordInfo rrInfo; ::memset( &rrInfo, 0, sizeof( rrInfo ) ); rrInfo.m_FileHandle = hHHDataBase; rrInfo.m_RecIndex = recIndex; rrInfo.m_pBytes = (BYTE *) &readBuf[ 0 ]; rrInfo.m_RecSize = READ_BUF_SIZE; rrInfo.m_TotalBytes = READ_BUF_SIZE; long retVal = ::SyncReadRecordByIndex( rrInfo ); if ( retVal ) { importSuccess = FALSE; fPLogMgr->Message( IDS_CANT_READ_DB ); } else { // The read succeeded, so copy the data onto fCompressedBuffer. fHHDBRecID = rrInfo.m_RecId; ASSERT( rrInfo.m_RecSize != 0 ); if ( fCompressedBuffer != NULL ) delete fCompressedBuffer; fCompressedBuffer = new BYTE[ rrInfo.m_RecSize ]; fCompressedLength = rrInfo.m_RecSize; ::memcpy( (void *) fCompressedBuffer, (void *) rrInfo.m_pBytes, fCompressedLength ); } return importSuccess; } // CNetPrefs::ImportPrefs {{anchor Iterating Through a Database}} '''データベースの始めから終わりまでの反復処理''' Sync マネージャはまた、ハンドヘルド上のデータベースの始めから終わりまでを反復して処理するのに使用できる関数も提供します。データベースの中のレコードを始めから終わりまで反復処理するには、まず {{goto SyncResetRecordIndex,SyncResetRecordIndex|C/C++ Sync Suite Reference601/4-2}} 関数を呼び出すことによってデータベースの現在のインデックスをリセットし、それから以下の取得するための関数の 1 つを繰り返し呼び出します: *{{span style='color:blue;font-family:monospace;',SyncReadNextRecInCategory}} はある特定のレコード カテゴリの中にある次のレコードを取得します。 *{{span style='color:blue;font-family:monospace;',SyncReadNextModifiedRec}} は(最後の同期の後に)変更された次のレコードを取得します。 *{{span style='color:blue;font-family:monospace;',SyncReadNextModifiedRecInCategory}} はある特定のレコード カテゴリーの中にある変更された次のレコードを取得します。 Sync マネージャは、データベースのオープン時に、データベースのための現在のデータベース反復インデックスをリセットします。その後に続く反復のためのインデックスをリセットするには、{{goto SyncResetRecordIndex,SyncResetRecordIndex|C/C++ Sync Suite Reference601/4-2}} 関数を呼び出さなくてはなりません。 {{goto Listing 10.3,コード 10.3}} はハンドヘルド データベースの中の変更された各レコードを取得するために {{goto SyncReadNextmodifiedRec,SyncReadNextModifiedRec()|C/C++ Sync Suite Reference601/4-2}} を使用するコードを示しています。 {{anchor Listing 10.3}} '''コード 10.3 ハンドヘルド レコードを読み込むための反復関数の使用''' CRawRecordInfo rawRecord; retval = AllocateRawRecordMemory(rawRecord, EXPENSE_RAW_REC_MEM); // Read in each modified remote record one at a time. while (!err && !retval) { if (!(err = SyncReadNextModifiedRec(rawRecord))) { // Convert from raw record format to CExpenseRecord. if (!m_pDTConvert->ConvertFromRemote(remRecord, rawRecord)) { // Synchronize the record obtained from the handheld. retval = SynchronizeRecord(remRecord, locRecord, backRecord); } else retval = CONDERR_CONVERT_FROM_REMOTE_REC; } memset(rawRecord.m_pBytes, 0, rawRecord.m_TotalBytes); } if (err && err != SYNCERR_FILE_NOT_FOUND) LogBadReadRecord(err); {{anchor Modifying a Database While Iterating}} '''反復中のデータベースの変更''' Sync マネージャは、データベースの始めから終わりまでの反復処理とデータベースの変更を同時にインタリーブ(訳者注: 多重プログラミング技法)することをサポートしません。これは、データベースの始めから終わりまでの反復処理している間にデータベースを変更しないようにロジックを組み立てる必要があることを意味します。Palm OS のバージョン 2.0 から、データベースの始めから終わりまでの反復処理中に、安全にデータベースからレコードを削除できるようになりました({{goto SyncPurgeAllRecsInCategory,SyncPurgeAllRecsInCategory|C/C++ Sync Suite Reference601/4-1}} 関数を除きます)。 {{anchor Writing Records to a Handheld Database}} '''ハンドヘルド データベースへのレコードの書き込み''' Sync マネージャは、ハンドヘルド上のデータベースにレコードまたはリソースを書き込むための関数をいくつか提供します。これらの関数はそれぞれ、{{goto CRawRecordInfo,CRawRecordInfo|C/C++ Sync Suite Reference601/4-1}} クラスのあるオブジェクトの中にあなたが保存したレコード情報を送り出します。これらの関数を使って、存在するレコードを変更するまたは新しいレコードをデータベースに追加することができます。 ハンドヘルド データベースにレコードを書き込むために、未加工レコード オブジェクトのある特定のフィールドに情報を詰め、それから同期マネージャのレコード書き込み関数の 1 つを呼び出します。関数はレコードをハンドヘルド上のデータベースに送ります。{{goto SyncWriteRec,SyncWriteRec|C/C++ Sync Suite Reference601/4-2}} 関数を使ってレコードをハンドヘルド データベースに書き込むことができ、{{goto SyncWriteResourceRec,SyncWriteResourceRec|C/C++ Sync Suite Reference601/4-2}} 関数を使ってリソースをハンドヘルド データベースに書き込むことができます。{{goto Listing 10.4,コード 10.4}} は、{{span style='color:blue;font-family:monospace;',SyncWriteRec()}} 関数を呼び出す見本の {{span style='color:blue;font-family:monospace;',ExportPrefs()}} メソッドを示しています。 {{anchor Listing 10.4}} '''コード 10.4 ハンドヘルドへのレコードの書き込み''' BOOL CNetPrefs::ExportPrefs( BYTE hHHDataBase ) { BOOL exportSuccess = TRUE; fHDataBase = hHHDataBase; if ( fCompressedLength != 0 ) { ASSERT( fCompressedBuffer != NULL ); // write to the HH database. CRawRecordInfo rrInfo; ::memset( &rrInfo, 0, sizeof( rrInfo ) ); rrInfo.m_FileHandle = hHHDataBase; rrInfo.m_RecId = fHHDBRecID; rrInfo.m_pBytes = fCompressedBuffer; rrInfo.m_RecSize = fCompressedLength; long retVal = ::SyncWriteRec( rrInfo ); if ( retVal ) { exportSuccess = FALSE; fPLogMgr->Message( IDS_CANT_WRITE_DB ); } } return exportSuccess; } // CNetPrefs::ExportPrefs !{{anchor Deleting Records in Handheld Database}}ハンドヘルド データベースの中のレコードの削除 {{goto top,^TOP^}} データベースからレコードまたはリソースを削除するために同期マネージャ関数を使用するとき、レコードまたはリソースはデータベースから直ちに削除され、取り外されます(原文: deleted and removed)。これは、レコードを削除するハンドヘルド上のアプリケーション呼び出し - 削除(delete)するときはレコードにマークを付けるだけで、取り外す(remove)ときはただちに取り外します - とは対照的です。 ::NOTE :::{{span style='color:blue;font-family:monospace;',Delete}} と {{span style='color:blue;font-family:monospace;',Purge}} で始まる同期マネージャ関数は両方とも''ただちに''オブジェクトを削除します。 Sync マネージャはデータベースからレコードまたはリソースを削除するためにいくつかの関数を提供します。これらの関数を使用するために、データを {{goto CRawRecordInfo,CRawRecordInfo|C/C++ Sync Suite Reference601/4-1}} クラスのあるオブジェクトの指定されたフィールドに代入します。それから {{goto Table 10.4,表 10.4}} の中で説明されている関数の 1 つを呼び出します。 {{anchor Table 10.4}} '''表 10.4 単一のレコードを削除するための関数''' ,関数,説明 ,"{{goto SyncDeleteRec,SyncDeleteRec|C/C++ Sync Suite Reference601/4-1}}",レコード データベースからレコードを削除します。 ,"{{goto SyncDeleteResourceRec,SyncDeleteResourceRec|C/C++ Sync Suite Reference601/4-1}}",リソース データベースから指定されたリソースを削除します。 {{goto Table 10.5,表 10.5}} の中で説明されている関数の 1 つを呼び出すことによって複数のレコードを削除することができます。 {{anchor Table 10.5}} '''表 10.5 複数のレコードを削除するための関数''' ,関数,説明 ,"{{goto SyncPurgeDeleteRecs,SyncPurgeDeleteRecs|C/C++ Sync Suite Reference601/4-1}}",レコード データベースの中の先立って削除されたまたはアーカイブされたというマークを付けられているすべてのレコードを削除します。 ,"{{goto SyncPurgeAllRecs,SyncPurgeAllRecs|C/C++ Sync Suite Reference601/4-1}}",ハンドヘルド上のレコード データベースの中のすべてのレコードを削除します。 ,"{{goto SyncPurgeAllRecsInCategory,SyncPurgeAllRecsInCategory|C/C++ Sync Suite Reference601/4-1}}",ハンドヘルド上のレコード データベースから指定されたカテゴリの中にあるすべてのレコードを削除します。 ,"{{goto SyncDeleteAllResourceRec,SyncDeleteAllResourceRec|C/C++ Sync Suite Reference601/4-1}}",リソース データベースからすべてのリソースを削除します。 !{{anchor Cleaning Up Records}}レコードのクリーン アップ {{goto top,^TOP^}} {{goto Table 10.6,表 10.6}} の中で示されている関数の 1 つを使って、同期操作の終了時に、レコードの状態フラグをクリアすることができます。 {{anchor Table 10.6}} '''表 10.6 レコードをクリーン アップするための関数''' ,関数,説明 ,"{{goto SyncResetSyncFlags,SyncResetSyncFlags|C/C++ Sync Suite Reference601/4-2}}",ハンドヘルド上のオープンされているレコード データベースの中のすべてのレコードの変更されたフラグをリセットします。オープンされているレコード データベースまたはリソース データベースのためのバックアップ日付をリセットします。 !{{anchor Closing Your Database}}データベースのクローズ {{goto top,^TOP^}} ハンドヘルド データベースとの同期が終了した後、{{goto Listing 10.1,コード 10.1}} の中で示されているように、それをクローズするために {{goto SyncCloseDB,SyncCloseDB|C/C++ Sync Suite Reference601/4-1}} 関数を呼び出さなくてはなりません。C API-ベース コンジットと Java-ベース コンジットはいつでもただ 1 つのデータベースをオープンすることを許可します。COM-ベース コンジットは 1 度に 1 つ以上のデータベースをオープンすることができます。 ::重要 :::C API-ベース コンジットまたは Java-ベース コンジットの中でデータベースをオープンする場合、コンジットを終了する前にそれをクローズしなくてはなりません; さもないと、他のコンジットはそれらのデータベースをオープンすることができなくなります。 {{div_end}} {{div_begin "style='border-top-style:solid;border-top-width:1px;border-top-color:silver;'"}} [[← 9 章に戻る|Introduction to Conduit Development601/9]] [[↑トップへ|Introduction to Conduit Development601]] [[付録 A に進む →|Introduction to Conduit Development601/A]] {{div_end}}