about dev guide (transaction handling with using syntax)
--------------------------------------------------------

                 Key: IBATISNET-236
                 URL: https://issues.apache.org/jira/browse/IBATISNET-236
             Project: iBatis for .NET
          Issue Type: Improvement
          Components: DataAccess
    Affects Versions: DataAccess 1.9 .1
         Environment: Microsoft Windows XP Professional Service Pack 2   
5.1.2600
Microsoft .NET Framework 1.1.4322.2407
Intel(R) Pentium(R) 4 CPU 3.00GHz
1536 MB RAM
            Reporter: noriyuki shimbo
            Priority: Trivial


I'm using Data Access with SQL Mapper.

See the example in the Data Access Object  Dev Guilde 1.9.1(and lower edition) 
Chapter5 - 5-5 - Working with Connection and Transactions - Example 5.6 
using ( IDalSession session = daoManager.OpenConnection() )
{
Account account = NewAccount();
accountDao.Create(account);
}
using ( IDalSession session = daoManager.BeginTransaction() )
{
Account account = NewAccount();
Account account2 = accountDao.GetAccountById(1);
account2.EmailAddress = "[EMAIL PROTECTED]";
accountDao.Create(account);
accountDao.Update(account2);
session.Complete(); // Commit
}

The example code above is not kind enough. If daoManager.BeginTransaction() 
fails due to network trouble or connection timeout or something, the instance 
of IDalsession is null, so Dispose method is not called. This leaves 
SqlMapSession remain in the ISessionStore(CallContextSessionStore) and the next 
transactions all fails to produce exceptions like below even if recovered from 
network trouble.

IBatisNet.DataMapper.Exceptions.DataMapperException: SqlMap could not invoke 
BeginTransaction(). A Transaction is already started. Call CommitTransaction() 
or RollbackTransaction first.

You can reproduce this result by writing iteration code in which "using syntax 
transaction" exists.

foreach(string key in keyList) 
{
try 
{
 // call transaction method which includes the code lilke Example 5.6 here
} 
catch (Exception e) 
{
 Console.WriteLine(e.ToString());
 Console.WriteLine(e.StackTrace);
// continue next
}
}

My workaround so far is to call daoManager.CloseConnection() in the catch block 
like below and it works.
try
{
using ( IDalSession session = daoManager.OpenConnection() )
{
 Account account = NewAccount();
 accountDao.Create(account);
}
}
catch (Exception ex)
{
 daoManager.CloseConnection();
 throw new RDBAccessException("message",ex);
}

try
{
 using ( IDalSession session = daoManager.BeginTransaction() )
 {
  Account account = NewAccount();
  Account account2 = accountDao.GetAccountById(1);
  account2.EmailAddress = "[EMAIL PROTECTED]";
  accountDao.Create(account);
  accountDao.Update(account2);
  session.Complete(); // Commit
 }
}
catch (Exception ex)
{
 daoManager.CloseConnection();
 throw new RDBAccessException("message",ex);
}


I'm using Data Access with SQL Mapper.

You can see the example in the Data Access Guilde 1.9.1(and lower edition) 
Chapter5 - 5-5 - Working with Connection and Transactions - Example 5.6 
using ( IDalSession session = daoManager.OpenConnection() )
{
 Account account = NewAccount();
 accountDao.Create(account);
}
using ( IDalSession session = daoManager.BeginTransaction() )
{
 Account account = NewAccount();
 Account account2 = accountDao.GetAccountById(1);
 account2.EmailAddress = "[EMAIL PROTECTED]";
 accountDao.Create(account);
 accountDao.Update(account2);
 session.Complete(); // Commit
}

The example code above is not kind enough. If daoManager.OpenConnection() or 
daoManager.BeginTransaction() fails due to network trouble or connection 
timeout or something, the instance of IDalsession is null, so Dispose method is 
not called. This leaves SqlMapSession remain in the 
ISessionStore(CallContextSessionStore) and the next transactions all fails to 
produce an exception like below even if recovered from network trouble.

IBatisNet.DataMapper.Exceptions.DataMapperException: SqlMap could not invoke 
BeginTransaction(). A Transaction is already started. Call CommitTransaction() 
or RollbackTransaction first.

You can reproduce this result by writing iteration code in which "using syntax 
transaction" exists.

foreach(string key in keyList) 
{
 try 
 {
  // call transaction method which includes the code lilke Example 5.6 here
 } 
 catch (Exception e) 
 {
  Console.WriteLine(e.ToString());
  Console.WriteLine(e.StackTrace);
  // continue next
}
}

My workaround so far is to call daoManager.CloseConnection() in the catch block 
like below and it works.
try
{
 using ( IDalSession session = daoManager.OpenConnection() )
 {
   Account account = NewAccount();
   accountDao.Create(account);
 }
}
catch (Exception ex)
{
 daoManager.CloseConnection();
 throw new RDBAccessException("message",ex);
}

try
{
 using ( IDalSession session = daoManager.BeginTransaction() )
 {
 Account account = NewAccount();
 Account account2 = accountDao.GetAccountById(1);
 account2.EmailAddress = "[EMAIL PROTECTED]";
 accountDao.Create(account);
 accountDao.Update(account2);
 session.Complete(); // Commit
 }
}
catch (Exception ex)
{
 daoManager.CloseConnection();
 throw new RDBAccessException("message",ex);
}

I think it will be better to describe this matter in the document.
 If you have the other better way please add it to the document.

Thanks.



-- 
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.

Reply via email to