株式会社キャッチアップで働くエンジニアのブログです。

技術雑記

[C#] TableAdapter にトランザクション機能を実装するクラス

Twitter bookmark Facebook LINE Pocket Feedly RSS

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 ソースコードのインデントが崩れていたので修正しました。

Twitter bookmark Facebook LINE Pocket Feedly RSS