You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@ibatis.apache.org by "noriyuki shimbo (JIRA)" <ib...@incubator.apache.org> on 2007/08/01 04:18:53 UTC

[jira] Created: (IBATISNET-236) about dev guide (transaction handling with using syntax)

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 = "someotherAddress@somewhere.com";
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 = "someotherAddress@somewhere.com";
  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 = "someotherAddress@somewhere.com";
 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 = "someotherAddress@somewhere.com";
 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.