Extensible Storage Engineでのデータベースへのアクセス方法を示します。
大雑把な流れを解説します。
まず必要となる変数を宣言しておくのですが、それぞれが初期化されたものであると示すために、これこれ.Nilを代入しておきます。
ここではテーブルの一覧を取得するのでシーケンシャルで読み込むのですが、そのシーケンシャルでアクセスするためにJET_RETINFO型の変数retInfoを宣言し、itagSequenceを1にしておきます。
データベースのページサイズを取得するためにApi.JetGetDatabaseFileInfo()でページサイズを取得しておきます。
そしてSystemParameters.DatabasePageSizeにその取得した値を設定しておきます。
Api.JetCreateInstance()でインスタンス変数を作成します。
Api.JetSetSystemParameter()で色々な値を設定します。
ログファイルやチェックポイントのファイル名の基本の名前とかです。(例ではedb)
Api.JetInit()で初期化します。
この初期化の前に色々な値の設定をしておかないといけません。
Api.JetBeginSession()でセッションの開始をします。
Api.JetAttachDatabase()でデータベースをアタッチします。
Api.JetOpenDatabase()でデータベースを開きます。
Api.JetBeginTransaction()でトランザクションを開始します。
Api.JetGetColumnInfo()で目的のテーブルのカラム情報を取得します。
Api.JetOpenTable()で目的のテーブルを開きます。
Api.JetSetTableSequential()でシーケンシャルでアクセスすることを知らせます。
Api.JetMove()を使ってカレント行を1行目に設定します。
Api.JetRetrieveColumn()で目的のカラムのデータを取得します。
ここで取得したデータは自身が必要とするデータ型に適宜変換する必要があります。
Api.JetMove()を使って次の行に移ります。
最後の行まで行って、そこで次の行に移ろうとするとEsentNoCurrentRecordException型のエラーが出ますが、それが正常なのでApi.JetCommitTransaction()でコミットします。
ロールバックはApi.JetRollback()でします。
この後、後処理をするのですが、きちんとしないと次にアクセスするときにエラーになってデータベースの修復が必要です。
途中でエラーになってもどこまで処理が進んだかによって後処理をきちんとしないといけないようです。
サンプルではその対処が入っています。
C#
JET_TABLEID tableId = JET_TABLEID.Nil;
JET_COLUMNBASE columnRowId;
byte[] data = new byte[1024 * 5];
int dataSize = 1024 * 5;
int acDataSize = 0;
JET_RETINFO retInfo = new JET_RETINFO();
//これを設定しないとシーケンシャルな読み取りとか出来ないみたい。
retInfo.itagSequence = 1;
//ファイルのデータベースのページサイズの取得
Api.JetGetDatabaseFileInfo(strDatabase, out pageSize, JET_DbInfo.PageSize);
JET_SESID sesid = JET_SESID.Nil;
JET_DBID dbid = JET_DBID.Nil;
JET_INSTANCE instance = JET_INSTANCE.Nil;
//データベースのページサイズの設定
//これがファイルと合わないとエラーになる
SystemParameters.DatabasePageSize = pageSize;
try
{
//インスタンス変数の作成
Api.JetCreateInstance(out instance, "instance");
//データベースのいろいろな値の設定
//ここの値が違うとうまく動作しない。
Api.JetSetSystemParameter(instance, JET_SESID.Nil, JET_param.BaseName, 0, "edb");
//初期化
Api.JetInit(ref instance);
//セッションの開始
Api.JetBeginSession(instance, out sesid, null, null);
//データベースのアタッチ
Api.JetAttachDatabase(sesid, strDatabase, AttachDatabaseGrbit.None);
blnAttatched = true;
try
{
//データベースを開く
Api.JetOpenDatabase(sesid, strDatabase, null, out dbid, OpenDatabaseGrbit.None);
//トランザクションの開始
Api.JetBeginTransaction(sesid);
//目的のテーブルのカラムを取得
Api.JetGetColumnInfo(sesid, dbid, "Favorites", CONST_ROWID_COLUMN_NAME, out columnRowId);
//目的のテーブルを開く
Api.JetOpenTable(sesid, dbid, "Favorites", null, 0, OpenTableGrbit.Sequential, out tableId);
blnOpenTable = true;
//テーブルをシーケンシャルでアクセスしたい時
Api.JetSetTableSequential(sesid, tableId, SetTableSequentialGrbit.None);
try
{
//テーブルの先頭行に移動
Api.JetMove(sesid, tableId, JET_Move.First, MoveGrbit.None);
for (;;)
{
data = new byte[data.Length];
DataRow dr = this._dt.NewRow();
//目的のカラムのデータを取得
Api.JetRetrieveColumn(sesid, tableId, columnRowId.columnid, data, dataSize, out acDataSize, RetrieveColumnGrbit.None, retInfo);
dr[CONST_ROWID_COLUMN_NAME] = BitConverter.ToInt32(data, 0);
data = new byte[data.Length];
this._dt.Rows.Add(dr);
Api.JetMove(sesid, tableId, JET_Move.Next, MoveGrbit.None);
}
}
catch(EsentNoCurrentRecordException exNoRecord)
{
//何もしない
//正常終了
Api.JetCommitTransaction(sesid, CommitTransactionGrbit.None);
}
catch (Exception ex)
{
//エラー時のロールバック
Api.JetRollback(sesid, RollbackTransactionGrbit.None);
}
}
catch (Exception ex)
{
if (blnOpenTable)
{
//エラー時のロールバック
Api.JetRollback(sesid, RollbackTransactionGrbit.None);
blnOpenTable = false;
}
MessageBox.Show(ex.Message);
retResult = false;
}
finally
{
}
}
catch (Exception ex)
{
if (blnOpenTable)
{
//エラー時のロールバック
Api.JetRollback(sesid, RollbackTransactionGrbit.None);
blnOpenTable = false;
}
MessageBox.Show(ex.Message);
retResult = false;
}
finally
{
if (blnOpenTable)
{
//テーブルを閉じる
Api.JetCloseTable(sesid, tableId);
blnOpenTable = false;
}
if (dbid != JET_DBID.Nil)
{
//データベースを閉じる
Api.JetCloseDatabase(sesid, dbid, CloseDatabaseGrbit.None);
}
if (sesid != JET_SESID.Nil)
{
if (blnAttatched)
{
//データベースをでタッチする
Api.JetDetachDatabase(sesid, strDatabase);
blnAttatched = false;
}
//セッションを終了する
Api.JetEndSession(sesid, 0);
}
//インスタンスを無効にする
Api.JetTerm(instance);
}
