Quillでトランザクション
Quillでトランザクションをするためにはトランザクションをかけたいメソッドに[Transaction]属性をつけます
またApp.config内のdataSourcesタグのデータソースの設定で
を指定します。
<dataSources> <!-- Oracle --> <dataSource name="Oracle"> <provider>Oracle</provider> <connectionString>...</connectionString> <class>Seasar.Extension.Tx.Impl.TxDataSourceImpl</class> </dataSource> </dataSources>
このようにしておいてトランザクションをかけたいメソッドに[Transaction]属性
をつけると、このメソッドから例外が発生したときにRollbackされます
[Transaction] public void RegisterData() { try { // データ登録ロジック } catch(Exception ex) { throw; } }
複数のデータソースでトランザクションをかける場合はデータソース毎にカスタムトランザクション設定クラスの実装が必要です。
public class OracleTransactionSetting : AbstractTransactionSetting { protected override void SetupTransaction(IDataSource dataSource) { // TransactionContext _transactionContext = new TransactionContext(); TransactionContext txContext = (TransactionContext)_transactionContext; txContext.DataSouce = dataSource; txContext.IsolationLevel = IsolationLevel.ReadCommitted; // TransactionContextを使用するデータソースにも設定 Type dataSourceType = dataSource.GetType(); if (typeof(SelectableDataSourceProxyWithDictionary).IsAssignableFrom( dataSourceType)) { ((SelectableDataSourceProxyWithDictionary)dataSource) .SetTransactionContext(txContext); } else if (typeof(TxDataSource).IsAssignableFrom(dataSourceType)) { ((TxDataSource)dataSource).Context = txContext; } // TransactionInterceptor LocalRequiredTxHandler handler = new LocalRequiredTxHandler(); handler.Context = txContext; _transactionInterceptor = new TransactionInterceptor(handler); ((TransactionInterceptor)_transactionInterceptor).TransactionStateHandler = txContext; } public override String DataSourceName { get { return "Oracle"; } // App.config内のデータソース設定の<dataSource name="Oracle"> の記述に合わせる } }
トランザクションをかけたい箇所に[Transaction]属性をつけます
[Transaction(typeof(OracleTransactionSetting))] public void RegisterData() { try { // データ登録ロジック } catch(Exception ex) { throw; } }
[seasar-dotnet:1210] Quill で複数データソースでのトランザクション制御に失敗するで議論されていますが、複数のデータソースがある場合トランザクションに失敗するようです。
public class OracleTransactionSetting : AbstractTransactionSetting { protected override void SetupTransaction(IDataSource dataSource) { // TransactionContext _transactionContext = TransactionContextCreator.GetTransactionContext(dataSource); TransactionContext txContext = (TransactionContext)_transactionContext; // TransactionContextを使用するデータソースにも設定 Type dataSourceType = dataSource.GetType(); if (typeof(SelectableDataSourceProxyWithDictionary).IsAssignableFrom( dataSourceType)) { ((SelectableDataSourceProxyWithDictionary)dataSource) .SetTransactionContext(txContext); } else if (typeof(TxDataSource).IsAssignableFrom(dataSourceType)) { ((TxDataSource)dataSource).Context = txContext; } // TransactionInterceptor LocalRequiredTxHandler handler = new LocalRequiredTxHandler(); handler.Context = txContext; _transactionInterceptor = new TransactionInterceptor(handler); ((TransactionInterceptor)_transactionInterceptor).TransactionStateHandler = txContext; } public override String DataSourceName { get { return "Oracle"; } } } public class PostgreSQLTransactionSetting : AbstractTransactionSetting { protected override void SetupTransaction(IDataSource dataSource) { // TransactionContext _transactionContext = TransactionContextCreator.GetTransactionContext(dataSource); TransactionContext txContext = (TransactionContext)_transactionContext; // TransactionContextを使用するデータソースにも設定 Type dataSourceType = dataSource.GetType(); if (typeof(SelectableDataSourceProxyWithDictionary).IsAssignableFrom( dataSourceType)) { ((SelectableDataSourceProxyWithDictionary)dataSource) .SetTransactionContext(txContext); } else if (typeof(TxDataSource).IsAssignableFrom(dataSourceType)) { ((TxDataSource)dataSource).Context = txContext; } // TransactionInterceptor LocalRequiredTxHandler handler = new LocalRequiredTxHandler(); handler.Context = txContext; _transactionInterceptor = new TransactionInterceptor(handler); ((TransactionInterceptor)_transactionInterceptor).TransactionStateHandler = txContext; } public override String DataSourceName { get { return "PostgreSQL"; } } } public static class TransactionContextCreator { private static TransactionContext _transactionContext = null; public static ITransactionContext GetTransactionContext(IDataSource dataSource) { if (_transactionContext == null) { _transactionContext = new TransactionContext(); _transactionContext.DataSouce = dataSource; _transactionContext.IsolationLevel = IsolationLevel.ReadCommitted; } return _transactionContext; } }
このようにすると良いらしいです