SQLまたはfoxproのいずれかで動作するC#プログラムでOleDbを使用しています。foxproデータを使用してトランザクションでステートメントを実行してから、RollBackを呼び出そうとしても、データが元に戻らないことに気付きました。SQLデータを使用して実行する場合、ロールバックは正常に機能するため、FoxProでも機能しない理由が少しわかりません。
私のテストアプリケーションでは、テーブル(TESTTABLE)からグリッドのデータソースにバインドされているデータテーブルにレコードを読み込んでいます。グリッドに行を追加し、保存ボタンを押してデータベーステーブルをクリアしてから、バインドされたDataTable内の現在のすべての行をループして、データベーステーブルに挿入し直します。理論的には、挿入中に問題が発生した場合、RollBackは削除を元に戻す必要があります。私が気付いているのは、挿入が失敗してトランザクションをロールバックした場合、テーブルが削除前の状態に戻るのではなく、削除されたレコードが削除されたままになることです。
2013年1月23日編集
VisualFoxPro9.0.0.5815を使用しています。テーブルが緩んでいるので、作成後にテーブルで「MAKETRANSACTABLE」を実行する必要があります。これを行うには、OleDbCommandを使用して次のコマンドを実行します
string commandText = "ExecScript('Use TESTTABLE In 0'+chr(13)+chr(10)+'MakeTransactable([TESTTABLE])')"
これが私が使っている保存機能です...
private void Save()
{
//Table: TESTTABLE
//Columns: REFERENCE NUMERIC(10), DESCRIPT VARCHAR(20)
bool CauseException = cbBreak.Checked;
//string SQLDbConnString = @"Provider=SQLNCLI;Server=TESTSERVER\\SQLExpress;Database=TESTDATA;Uid=test;Pwd=test;Connect Timeout=600";
string FoxProDbConnString = @"Provider=vfpoledb;Data Source=C:\Test\Data;Exclusive=false;Nulls=false;ConnectTimeOut=600;QueryTimeOut=600;";
using (OleDbConnection dbConn = new OleDbConnection(FoxProDbConnString))
{
dbConn.Open();
using (OleDbTransaction dbTran = dbConn.BeginTransaction())
{
try
{
//Run a delete command to remove all records from the table
string deletequery = "DELETE FROM TESTTABLE";
using (OleDbCommand cmd = new OleDbCommand(deletequery, dbConn, dbTran))
{
cmd.ExecuteNonQuery();
}
//Loop through the DataTable rows and insert them into the database table
foreach (DataRow row in dt.Rows)
{
string insertquery = "INSERT INTO TESTTABLE (REFERENCE, DESCRIPT) VALUES (?,?)";
using (OleDbCommand cmd = new OleDbCommand(insertquery, dbConn, dbTran))
{
if (CauseException)
{
cmd.Parameters.Add("ref", OleDbType.Numeric).Value = "THIS IS NOT A NUMERIC VALUE";
}
else
{
cmd.Parameters.Add("ref", OleDbType.Numeric).Value = Convert.ToDouble(row["reference"]);
}
cmd.Parameters.Add("descript", OleDbType.VarChar).Value = Convert.ToString(row["descript"]).Trim();
cmd.ExecuteNonQuery();
}
}
//If no exceptions were thrown during the inserts, commit the transaction
dbTran.Commit();
MessageBox.Show("Saved");
}
catch (Exception ex)
{
//If an exception occurs, RollBack the transaction. This SHOULD undo the delete.
dbTran.Rollback();
MessageBox.Show("Failed to save. Rolling back changes.");
}
}
}
}
2013年1月24日編集
System.Data.OleDbの代わりにSystem.Data.Odbcを使用して上記と同じコードをテストしたところ、トランザクションは完全に機能しました。次の接続文字列を使用しました。
string odbcConnStr = @ "Driver = {INTERSOLV dBASEFile(* .DBF)}; SourceDB = C:\ Test \ Data;";
ここでの問題は、特にvfpoledbプロバイダーがトランザクションを正しく処理していないことにあるように思われます。私が調べた別の方法は、ルーズテーブルの代わりにデータベースコンテナを使用することでしたが、「CREATEDATABASE」関数はvfpoledbでサポートされていないようです。