[ https://issues.apache.org/jira/browse/IBATISNET-212?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]
Gilles Bayon closed IBATISNET-212. ---------------------------------- Resolution: Fixed Fix Version/s: DataMapper 1.6.1 Assignee: Gilles Bayon In SVN, renames property as IsTransactionStart > Add the ability to track Open Transactions via IDalSession > ---------------------------------------------------------- > > Key: IBATISNET-212 > URL: https://issues.apache.org/jira/browse/IBATISNET-212 > Project: iBatis for .NET > Issue Type: Improvement > Components: DataMapper > Environment: Any > Reporter: Samuel Clough > Assigned To: Gilles Bayon > Fix For: DataMapper 1.6.1 > > Attachments: IDalSession.cs, SqlMapSession.cs > > > At times, a method call may need to call another method call as part of one > logical data insert/update operation. Currently the problem is that iBatis > does not expose in the session interface whether or not their is an open > transaction. Because of this, a method that may be called as part of a > larger data update has no way of checking to see if a transaction is open > before opening another one. Some RDMSs allow nested transactions and this is > not a problem, but other providers do not and it can become a problem. The > suggestion is that iBatis expose the _isOpenTransaction field on the session > via a property so that it can be checked in a method call when a method needs > to determine if it should open a transaction or not. > Below is a sample use case where ObjectB can be updated, but ObjectB is also > a property of ObjectA and when ObjectA is updated, the embedded ObjectB > should be updated as well all within one transaction. (This is just an > example, not great code). > class Example > { > private ISqlMapper _mapper = null; > > public Example() > { > _mapper = Mapper.Instance(); > } > public void UpdateA(ObjectA a) > { > _dataMapper.StartTransaction(); > _dataMapper.update("update-a", a); > UpdateB(a.ObjectB); > _dataMapper.CommitTransaction(); > } > public void UpdateB(ObjectB b) > { > bool existingTransaction = _dataMapper.TransactionOpen; > if (!existingTransaction) > { > _dataMapper.StartTransaction(); > } > _dataMapper.Update("update-b", b); > if (!existingTransaction) > { > _dataMapper.CommitTransaction(); > } > } > } > This has been a major need for us on some projects and I would suppose for > others as well. For that reason, we are proposing this enhancement rather > than creating some in house solution or a custom iBatis build. In order to > make the changes, the following changes would need to be made to the code: > The IBatisNet.Common.IDalSession interface would need the following new > property: > bool OpenTransaction{ get; } > The IBatisNet.DataMapper.SqlMapSession would need the following changes: > 1. Implement the new property to expose the existing field.: > public bool OpenTransaction > { > get { return _isOpenTransaction; } > } > 2. Update the CommitTransaction methods to be as follows including an update > to the _isOpenTransaction field: > /// <summary> > /// Commits the database transaction. > /// </summary> > /// <remarks> > /// Will close the connection. > /// </remarks> > public void CommitTransaction() > { > if (_logger.IsDebugEnabled) > { > _logger.Debug("Commit Transaction."); > } > _transaction.Commit(); > _transaction.Dispose(); > _isOpenTransaction = false; > if (_connection.State != ConnectionState.Closed) > { > this.CloseConnection(); > } > } > /// <summary> > /// Commits the database transaction. > /// </summary> > /// <param name="closeConnection">Close the connection</param> > public void CommitTransaction(bool closeConnection) > { > if (closeConnection) > { > this.CommitTransaction(); > } > else > { > _transaction.Commit(); > if (_logger.IsDebugEnabled) > { > _logger.Debug("Commit Transaction."); > } > _transaction.Dispose(); > _isOpenTransaction = false; > } > } > 3. Update the RollbackTransaction methods to set the state of the > _isOpenTransaction field as follows: > /// <summary> > /// Rolls back a transaction from a pending state. > /// </summary> > /// <remarks> > /// Will close the connection. > /// </remarks> > public void RollBackTransaction() > { > _transaction.Rollback(); > if (_logger.IsDebugEnabled) > { > _logger.Debug("RollBack Transaction."); > } > _transaction.Dispose(); > _transaction = null; > _isOpenTransaction = false; > if (_connection.State != ConnectionState.Closed) > { > this.CloseConnection(); > } > } > /// <summary> > /// Rolls back a transaction from a pending state. > /// </summary> > /// <param name="closeConnection">Close the connection</param> > public void RollBackTransaction(bool closeConnection) > { > if (closeConnection) > { > this.RollBackTransaction(); > } > else > { > if (_logger.IsDebugEnabled) > { > _logger.Debug("RollBack Transaction."); > } > _transaction.Rollback(); > _transaction.Dispose(); > _transaction = null; > _isOpenTransaction = false; > } > } > This would be very helpful when developing against RDMS servers and/or > providers that do not support nested transactions as well as be more > efficient than nested transactions. -- This message is automatically generated by JIRA. - You can reply to this email to add a comment to the issue online.