TableAdapterにトランザクションを実装
TableAdapterにトランザクションを実装

今は Visual C# 2005 Express Edition にて ADO.NET 2.0 Provider for SQLiteを利用してクライアントアプリの開発しています。

TableAdapterにてINSERTやupdateするとどうも更新が遅いので、Googleで調べたら

> http://journal.mycom.co.jp/special/2004/php5/007.html
> SQLiteでは明示的にトランザクションを開始しない限り、INSERT処理の前後に必ず”BEGIN”、”COMMIT”が実行される。

とのことでした。

で、色々試行錯誤して下記のVB記事を参考にC#&SQLite用のトランザクションの処理を追加。

TableAdapterにトランザクションを実装 / うなまな Blog
http://www.ailight.jp/blog/unaap/archive/2007/02/13/13566.aspx

ソースは次のとおりです。

とりあえず貼り付けて起きます、何か問題あったら連絡ください。

TableAdapterにトランザクション機能を実装するクラス
TableAdapterTransactor.cs

using System;
using System.Collections.Generic;
using System.Text;
using System.Data;
using System.Data.SQLite;
using System.Reflection;
/// 
/// TableAdapterにトランザクション機能を実装するクラス
/// 
/// 
/// 利用方法の例
///     TableAdapterTransactor tat = new TableAdapterTransactor();
///     Data1TableAdapter taData1 = new Data1TableAdapter();
///     Data2TableAdapter taData2 = new Data2TableAdapter();
///
///     tat.AddTableAdapter(taData1);
///     tat.AddTableAdapter(taData2);
///     tat.BeginTransaction();
///     try {
///         taData1.Insert...();
///         taData2.Insert...();
///         tat.Commit();
///     }
///     catch (Exception ex) {
///         tat.Rollback();
///     }
///
/// http://www.ailight.jp/blog/unaap/archive/2007/02/13/13566.aspx
/// 
class TableAdapterTransactor
{
private SQLiteConnection _conn = null;
private SQLiteTransaction _trans = null;
private List
_tableAdapters = new List();    #region "Pプロシージャ - GetConnection                     [TableAdapterのConnectionを取得する]"
/// 
/// TableAdapterのConnectionを取得する
/// 
///
TableAdapter     /// 取得したConnection
/// 
private SQLiteConnection GetConnection(object tableAdapter)
{
Type type = tableAdapter.GetType();
PropertyInfo connectionProperty = type.GetProperty("Connection", BindingFlags.NonPublic | BindingFlags.Instance);
SQLiteConnection connection = (SQLiteConnection)connectionProperty.GetValue(tableAdapter, null);
return connection;
}
#endregion    #region "Pプロシージャ - SetConnection                     [TableAdapterのConnectionを設定する]"
/// 
/// TableAdapterのConnectionを設定する
/// 
///
TableAdapter     /// Connection     /// 
private void SetConnection(object tableAdapter, SQLiteConnection connection)
{
Type type = tableAdapter.GetType();
PropertyInfo connectionProperty = type.GetProperty("Connection", BindingFlags.NonPublic | BindingFlags.Instance);
connectionProperty.SetValue(tableAdapter, connection, null);
}
#endregion    #region "Pプロシージャ - GetAdapter                        [TableAdapterのDataAdapterを取得する]"
/// 
/// TableAdapterのDataAdapterを取得する
/// 
///
TableAdapter     /// 取得したDataAdapter
/// 
private SQLiteDataAdapter GetAdapter(object tableAdapter)
{
Type type = tableAdapter.GetType();
FieldInfo adapterField = type.GetField("_adapter", BindingFlags.NonPublic | BindingFlags.Instance);
SQLiteDataAdapter adapter = (SQLiteDataAdapter)adapterField.GetValue(tableAdapter);
return adapter;
}
#endregion
#region "Pプロシージャ - SetAdapter                        [TableAdapterのDataAdapterを設定する]"
/// 
/// TableAdapterのDataAdapterを設定する
/// 
/// TableAdapter     /// DataAdapter     /// 
private void SetAdapter(object tableAdapter, SQLiteDataAdapter adapter)
{
Type type = tableAdapter.GetType();
FieldInfo adapterField = type.GetField("_adapter", BindingFlags.NonPublic | BindingFlags.Instance);
adapterField.SetValue(tableAdapter, adapter);
}
#endregion
#region "Pプロシージャ - InitAdapter                       [TableAdapterのInitAdapterメソッドを呼び出す]"
/// 
/// TableAdapterのInitAdapterメソッドを呼び出す
/// 
/// TableAdapter     /// 利用しない
private void InitAdapter(object tableAdapter)
{
Type type = tableAdapter.GetType();
MethodInfo mi = type.GetMethod("InitAdapter", BindingFlags.NonPublic | BindingFlags.Instance);
mi.Invoke(tableAdapter, null);
}
#endregion
#region "Pプロシージャ - InitCommandCollection             [TableAdapterのInitCommandCollectionメソッドを呼び出す]"
/// 
/// TableAdapterのInitCommandCollectionメソッドを呼び出す
/// 
/// TableAdapter     /// 利用しない
private void InitCommandCollection(object tableAdapter)
{
Type type = tableAdapter.GetType();
MethodInfo mi = type.GetMethod("InitCommandCollection", BindingFlags.NonPublic | BindingFlags.Instance);
mi.Invoke(tableAdapter, null);
}
#endregion
#region "Pプロシージャ - SetTransactionCommands            [TableAdapterのCommandCollectionのTransactionを設定する]"
/// 
/// TableAdapterのCommandCollectionのTransactionを設定する
/// 
/// TableAdapter     /// Transaction     /// 
private void SetTransactionCommands(object tableAdapter, SQLiteTransaction transaction)
{
Type type = tableAdapter.GetType();
PropertyInfo commandsProperty = type.GetProperty("CommandCollection", BindingFlags.NonPublic | BindingFlags.Instance);
SQLiteCommand[] commands = (SQLiteCommand[])commandsProperty.GetValue(tableAdapter, null);
foreach (SQLiteCommand command in commands)
{
command.Transaction = transaction;
}
this.SetConnection(tableAdapter, transaction.Connection);
}
#endregion
#region "Pプロシージャ - SetTransactionAdapter             [TableAdapterのDataAdapterのTransactionを設定する]"
/// 
/// TableAdapterのDataAdapterのTransactionを設定する
/// 
/// TableAdapter     /// Transaction     /// 
private void SetTransactionAdapter(object tableAdapter, SQLiteTransaction transaction)
{
SQLiteDataAdapter adp = this.GetAdapter(tableAdapter);
if (adp.InsertCommand != null)
{
adp.InsertCommand.Transaction = transaction;
}
if (adp.DeleteCommand != null)
{
adp.DeleteCommand.Transaction = transaction;
}
if (adp.UpdateCommand != null)
{
adp.UpdateCommand.Transaction = transaction;
}
this.SetAdapter(tableAdapter, adp);
//this.InitCommandCollection(tableAdapter)
}
#endregion
#region "メソッド - AddTableAdapter                        [TableAdapterを追加する]"
/// 
/// TableAdapterを追加する
/// 
/// TableAdapter     /// 
public void AddTableAdapter(object tableAdapter)
{
this._tableAdapters.Add(tableAdapter);
}
#endregion
#region "メソッド - BeginTransaction                       [トランザクションを開始する]"
/// 
/// トランザクションを開始する
/// 
/// 開始する前に、AddTableAdapterメソッドで対象となるTableAdapterを追加すること
public void BeginTransaction()
{
int counter = 0;
foreach (object adapter in this._tableAdapters)
{
counter += 1;
if (counter == 1)
{
this._conn = this.GetConnection(adapter);
if (this._conn.State != ConnectionState.Open)
{
this._conn.Open();
}
this._trans = this._conn.BeginTransaction();
}
this.SetConnection(adapter, this._conn);
this.SetTransactionAdapter(adapter, this._trans);
this.SetTransactionCommands(adapter, this._trans);
}
}
/// 
/// トランザクションを開始する
/// 
/// コネクション     /// 
public void BeginTransaction(SQLiteConnection conn)
{
this._conn = conn;
if (this._conn.State != ConnectionState.Open)
{
this._conn.Open();
}
this._trans = this._conn.BeginTransaction();
foreach (object adapter in this._tableAdapters)
{
this.SetConnection(adapter, this._conn);
this.SetTransactionAdapter(adapter, this._trans);
this.SetTransactionCommands(adapter, this._trans);
}
}
/// 
/// トランザクションを開始する
/// 
/// トランザクション     /// 
public void BeginTransaction(SQLiteTransaction trans)
{
this._conn = trans.Connection;
this._trans = trans;
foreach (object adapter in this._tableAdapters)
{
this.SetConnection(adapter, this._conn);
this.SetTransactionAdapter(adapter, this._trans);
this.SetTransactionCommands(adapter, this._trans);
}
}
#endregion
#region "メソッド - Commit                                 [トランザクションをコミットする]"
/// 
/// トランザクションをコミットする
/// 
/// 
public void Commit()
{
try
{
this._trans.Commit();
}
catch (Exception ex)
{
this._trans.Rollback();
throw ex;
}
finally
{
if ((this._conn.State == ConnectionState.Open))
{
this._conn.Close();
}
}
}
#endregion
#region "メソッド - Rollback                               [トランザクションをロールバックする]"
/// 
/// トランザクションをロールバックする
/// 
/// 
public void Rollback()
{
this._trans.Rollback();
if ((this._conn.State == ConnectionState.Open))
{
this._conn.Close();
}
}
#endregion
}
}
//eof


はずかしながら↓
ttp://bbs.wankuma.com/index.cgi?mode=al2&namber=4858


※ 2008/12/5 ソースコードのインデントが崩れていたので修正しました。