S2Tx.NETの機能を使って、.NETオブジェクトに対して、
Aspectでトランザクションの自動管理機能を組み込むことができます。
Aspectを適用については、こちらの注意点を確認して下さい。
トランザクションの自動管理には、ローカルトランザクションとMicrosoft 分散トランザクション コーディネータ (MS DTC)
の2つをサポートしています。
組む込むことのできるトランザクション属性は次のとおりです。
S2Container.NETが標準で用意しているTx.dicon(ローカルトランザクション用)とDTCTx.dicon(MS DTC用)には、
次のトランザクション属性に対応したAdviceが定義されています。
コンポーネント名がAdviceの名前です。
Tx.diconとDTCTx.diconは、source/Seasarフォルダに用意されています。
属性 |
コンポーネント名 |
説明 |
Required |
LocalTx.RequiredTx
(ローカルトランザクション用)
|
トランザクションが存在する場合はこれを共有し、
必要に応じて新しいトランザクションを作成します。
|
DTCTx.RequiredTx
(MS DTC用)
|
RequiresNew |
LocalTx.RequiresNewTx
(ローカルトランザクション用)
|
現在のコンテキストの状態とは関係なく、
新しいトランザクションでコンポーネントを作成します。
|
DTCTx.RequiresNewTx
(MS DTC用)
|
Supported |
LocalTx.SupportedTx
(ローカルトランザクション用)
|
トランザクションが存在する場合はこれを共有します。
|
DTCTx.SupportedTx
(MS DTC用)
|
NotSupported |
Tx.NotSupportedTx
(ローカルトランザクション用)
|
制御するトランザクションがないコンテキストでコンポーネントを作成します。
|
DTCTx.NotSupportedTx
(MS DTC用)
|
ローカルトランザクションを利用するためには、Seasar.Extension.Tx.Impl.TxDataSourceから
コネクションを取得します。コネクションのオープン、クローズは
Advice(MethodInterceptor)が管理するため、
DAO (Data Access Object)では行いません。DAOにTxDataSourceをインジェクションしてもらうために
Seasar.Extension.ADO.IDataSource型のプロパティを用意します。
コネクション、トランザクション、コマンド、パラメータのオブジェクトはdataSourceから作成します。
従業員を扱うためのDAOインターフェースとDAO実装クラスは次のようになります。
EmployeeDao.cs
using System;
using System.Data;
using Seasar.Extension.ADO;
namespace Seasar.Examples.Reference.LocalTx
{
// 従業員を扱うためのDAOインターフェース
public interface IEmployeeDao
{
void Insert();
}
// 従業員を扱うためのDAO実装クラス
public class EmployeeDaoImpl : IEmployeeDao
{
private IDataSource dataSource;
// TxDataSourceをインジェクションしてもらうためのプロパティ
public IDataSource DataSource
{
set { dataSource = value; }
}
#region IEmployeeDao メンバ
public void Insert()
{
string sql = "insert into emp2 values(@empno, @ename, @deptnum)";
using(IDbCommand cmd = dataSource.GetCommand(sql,
dataSource.GetConnection(), dataSource.GetTransaction()))
{
cmd.Parameters.Add(dataSource.GetParameter("@empno", 99));
cmd.Parameters.Add(dataSource.GetParameter("@ename", "Sugimoto"));
cmd.Parameters.Add(dataSource.GetParameter("@deptnum", 31));
cmd.ExecuteNonQuery();
Console.WriteLine("EMPを追加しました。");
}
}
#endregion
}
}
IEmployeeDaoを実行するクラスは次のようになります。
LocalTxClient.cs
using System;
using Seasar.Framework.Container;
using Seasar.Framework.Container.Factory;
namespace Seasar.Examples.Reference.LocalTx
{
public class LocalTxClient
{
private static readonly String PATH
= "Seasar.Examples/Reference/LocalTx/LocalTxClient.dicon";
public LocalTxClient() {}
public void Main()
{
// S2コンテナを作成します
IS2Container container = S2ContainerFactory.Create(PATH);
// S2コンテナを初期化します
container.Init();
// S2コンテナからIEmployeeDaoを実装するコンポーネントを取り出します
IEmployeeDao dao = (IEmployeeDao) container.GetComponent(typeof(IEmployeeDao));
// 従業員を追加します
dao.Insert();
}
}
}
diconファイルは次のようになります。Required属性のトランザクションを適用するために、
EmployeeDaoImplのaspectにLocalTx.RequiredTxを指定してします。
LocalTxClient.dicon
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE components PUBLIC "-//SEASAR2.1//DTD S2Container//EN"
"http://www.seasar.org/dtd/components21.dtd">
<components>
<include path="Seasar.Examples/Tx.dicon" />
<component name="LocalTxClient" class="Seasar.Examples.Reference.LocalTx.LocalTxClient" />
<component class="Seasar.Examples.Reference.LocalTx.EmployeeDaoImpl">
<aspect>LocalTx.RequiredTx</aspect>
</component>
</components>
Tx.dicon
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE components PUBLIC "-//SEASAR2.1//DTD S2Container//EN"
"http://www.seasar.org/dtd/components21.dtd">
<components namespace="LocalTx">
<include path="Seasar.Examples/Ado.dicon" />
<component name="SqlDataSource" class="Seasar.Extension.Tx.Impl.TxDataSource">
<property name="DataProvider">Ado.SqlClient</property>
<property name="ConnectionString">
"Server=SQL Serverの名称;database=s2dotnetdemo;Integrated Security=SSPI"
</property>
</component>
<component class="Seasar.Extension.Tx.Impl.TransactionContext" />
<component name="RequiredTx" class="Seasar.Extension.Tx.TransactionInterceptor">
<arg>
<component class="Seasar.Extension.Tx.Impl.LocalRequiredTxHandler" />
</arg>
</component>
・・・
</components>
Ado.dicon
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE components PUBLIC "-//SEASAR2.1//DTD S2Container//EN"
"http://www.seasar.org/dtd/components21.dtd">
<components namespace="Ado">
<component name="SqlClient" class="Seasar.Extension.ADO.DataProvider">
<property name="ConnectionType">"System.Data.SqlClient.SqlConnection"</property>
<property name="CommandType">"System.Data.SqlClient.SqlCommand"</property>
<property name="ParameterType">"System.Data.SqlClient.SqlParameter"</property>
<property name="DataAdapterType">"System.Data.SqlClient.SqlDataAdapter"</property>
</component>
</components>
実行結果
DEBUG トランザクションを開始しました
EMPを追加しました。
DEBUG トランザクションをコミットしました
MS DTCによる分散トランザクションを利用するためには、MS DTCが利用できる環境でなければいけません。
ローカルトランザクションのようにTxDataSourceからコネクションをとらないといけないといった制限はありませんが、
データプロバイダに依存しないコーディングをするために、Seasar.Extension.ADO.Impl.DataSourceImpl
からコネクション、コマンド、パラメータのオブジェクトを作成します。
MS DTCを利用する場合は、1回のクエリ発行毎にコネクションをクローズしても、トランザクションは維持されます。
従業員を扱うためのDAOインターフェースとDAO実装クラスは次のようになります。
EmployeeDao.cs
using System;
using System.Data;
using Seasar.Extension.ADO;
namespace Seasar.Examples.Reference.DTCTx
{
// 従業員を扱うためのDAOインターフェース
public interface IEmployeeDao
{
void Insert();
}
// 従業員を扱うためのDAO実装クラス
public class EmployeeDaoImpl : IEmployeeDao
{
private IDataSource dataSource;
// DataSourceImplをインジェクションしてもらうためのプロパティ
public IDataSource DataSource
{
set { dataSource = value; }
}
#region IEmployeeDao メンバ
public void Insert()
{
using(IDbConnection cn = dataSource.GetConnection())
{
cn.Open();
string sql = "insert into emp2 values(@empno, @ename, @deptnum)";
using(IDbCommand cmd = dataSource.GetCommand(sql,cn))
{
cmd.Parameters.Add(dataSource.GetParameter("@empno", 99));
cmd.Parameters.Add(dataSource.GetParameter("@ename", "Sugimoto"));
cmd.Parameters.Add(dataSource.GetParameter("@deptnum", 31));
cmd.ExecuteNonQuery();
Console.WriteLine("EMPを追加しました。");
}
}
}
#endregion
}
}
IEmployeeDaoを実行するクラスは次のようになります。
DTCTxClient.cs
using System;
using Seasar.Framework.Container;
using Seasar.Framework.Container.Factory;
namespace Seasar.Examples.Reference.DTCTx
{
public class DTCTxClient
{
private static readonly String PATH
= "Seasar.Examples/Reference/DTCTx/DTCTxClient.dicon";
public DTCTxClient() {}
public void Main()
{
// S2コンテナを作成します
IS2Container container = S2ContainerFactory.Create(PATH);
// S2コンテナを初期化します
container.Init();
// S2コンテナからIEmployeeDaoを実装するコンポーネントを取り出します
IEmployeeDao dao = (IEmployeeDao) container.GetComponent(typeof(IEmployeeDao));
// 従業員を追加します
dao.Insert();
}
}
}
diconファイルは次のようになります。Required属性のトランザクションを適用するために、
EmployeeDaoImplのaspectにDTCTx.RequiredTxを指定します。
DTCTxClient.dicon
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE components PUBLIC "-//SEASAR2.1//DTD S2Container//EN"
"http://www.seasar.org/dtd/components21.dtd">
<components>
<include path="Seasar.Examples/DTCTx.dicon" />
<component name="DTCTxClient" class="Seasar.Examples.Reference.DTCTx.DTCTxClient" />
<component class="Seasar.Examples.Reference.DTCTx.EmployeeDaoImpl">
<aspect>DTCTx.RequiredTx</aspect>
</component>
</components>
DTCTx.dicon
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE components PUBLIC "-//SEASAR2.1//DTD S2Container//EN"
"http://www.seasar.org/dtd/components21.dtd">
<components namespace="DTCTx">
<include path="Seasar.Examples/Ado.dicon" />
<component name="SqlDataSource" class="Seasar.Extension.ADO.Impl.DataSourceImpl">
<property name="DataProvider">Ado.SqlClient</property>
<property name="ConnectionString">
"Server=SQL Serverの名称;database=s2dotnetdemo;Integrated Security=SSPI"
</property>
</component>
<component name="DTCTransactionStateHandler"
class="Seasar.Extension.Tx.Impl.DTCTransactionStateHandler" />
<component name="RequiredTx" class="Seasar.Extension.Tx.TransactionInterceptor">
<arg>
<component class="Seasar.Extension.Tx.Impl.DTCRequiredTxHandler" />
</arg>
</component>
・・・
</components>
Ado.diconと実行結果は、ローカルトランザクションの場合と同じです。
S2Container.NETには、Tx.diconおよびDTCTx.diconがあらかじめ用意(source/Seasar)されています。
Adviceのコンポーネント名をaspectタグのボディに指定するだけなので簡単です。
簡単にトランザクション管理機能が組み込めることがわかってもらえたと思います。
Tx.diconおよびDTCTx.dionに定義されているAdviceは、コンポーネントが例外をスローした場合はトランザクションをロールバックします.
|