Я использую OleDb в программе на C #, которая может работать как с SQL, так и с foxpro. Я заметил, что когда я запускаю операторы в транзакции с данными foxpro, а затем пытаюсь вызвать RollBack, данные не восстанавливаются. Откат отлично работает при работе с данными SQL, поэтому я немного смущен, почему он не работает и в FoxPro.
В моем тестовом приложении я читаю записи из таблицы (TESTTABLE) в таблицу данных, которая привязана к источнику данных для сетки. Я добавляю строки в сетку, а затем нажимаю кнопку сохранения, чтобы очистить таблицу базы данных, затем перебираю все текущие строки в привязанном DataTable, чтобы вставить их обратно в таблицу базы данных. Теоретически, если что-то пойдет не так во время вставки, RollBack должен отменить удаление. Я замечаю, что если вставка не удалась и я откатил транзакцию, удаленные записи останутся удаленными, а не таблица вернется к тому состоянию, в котором она была до удаления.
Изменить 23.01.2013
Я использую Visual FoxPro 9.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.");
}
}
}
}
Изменить 24.01.2013
Я протестировал тот же код выше, используя System.Data.Odbc вместо System.Data.OleDb, и транзакция прошла отлично. Я использовал следующую строку подключения:
строка odbcConnStr = @ "Драйвер = {INTERSOLV dBASEFile (* .DBF)}; SourceDB = C: \ Test \ Data;";
Мне кажется, что проблема здесь именно в том, что провайдер vfpoledb неправильно обрабатывает транзакции. Альтернативой, которую я изучал, было использование контейнеров баз данных вместо отдельных таблиц, но похоже, что функция «CREATE DATABASE» не поддерживается vfpoledb.