Details
-
Improvement
-
Status: Open
-
Trivial
-
Resolution: Unresolved
-
DataAccess 1.9 .1
-
None
-
None
-
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
sqlServer1.1 provider, oracleClient1.0 provider
Description
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
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
in sqlServer1.1 provider and oracleClient1.0 provider.
try
{
using ( IDalSession session = daoManager.OpenConnection() )
}
catch (Exception ex)
{
daoManager.CloseConnection();
throw new RDBAccessException("message",ex);
}
try
{
using ( IDalSession session = daoManager.BeginTransaction() )
}
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.