We've developed a client-server application using .NET Data Provider
1.6.3 
in the data layer of the server. Each client has a separate data access 
object on the server and is calling it via .NET Remoting. The
application 
worked fine in a production environment with about 12 clients for
several 
month's. Then I updated the data provider to v2.0. After a timespan from

some hours to some days one of the data access objects began to return 
IscExceptions, mostly "invalid transaction handle (expecting explicit 
transaction start)", on almost all following calls until the server was 
restarted. No changes with implementing data provider v1.7.1, so I had
to 
go back to v1.6.3.

I built a test environment and tried to reproduce and debug the error.
Each 
data access object of my application contains a common FbConnection
object 
and some FbDataAdapters with FbCommands for multiple use. There are 
procedures using temporary FbCommands too, e. g. each call creates a new

FbCommannd object with the common connection object. There's no explicit

Dispose() for those commands, so disposing should be done by garbage 
collector later. At the end of each call to the data access object the
Common connection will be closed for further use in the connection pool.

In normal operation state FbConnection.Close() releases all prepared 
commands and removes them from inner connection. I found, that in error 
state FbConnection.PreparedCommands doesn't contain the FbCommand object

that rises the exception during FbCommand.Execute(). So this command
isn't 
released and if it is used again subsequent it has still an (unvalid) 
prepared GdsStatement. The GdsDatabase of this statement meanwhile can 
point to an inner connection of the connection pool that is closed or
used 
by another thread. Calling GdsStatement.Execute() on such an unvalid 
statement rises an IscError.

But why PreparedCommands dosn't contains the command when closing 
connection? When garbage collector disposes an FbCommand object with an 
open FbConnection object, it calls
FbConnectionInternal.RemovePreparedCommand() 
in FbCommand.Release(). In RemovePreparedCommand() the garbage
collection 
thread calls PreparedCommands (get) and can cause a conflict with an 
application thread there. Sometimes the application thread creates a new

ArrayList for prepared commands and adds the first command. After that
the 
garbage collection thread creates a new empty ArrayList and replaces the

ArrayList with the new command.

I checked csv for .Net Data Provider v1.6.3. There's a
GC.SuppressFinalize() 
in the constructor of the FbCommand class. Therefore no errors occur in 
that version.

I added a explicit Dispose() to each temporary FbCommand and no further 
errors occured. Is this the recommended way to use FbCommand? I think it

would be useful to modify the provider to prevent that garbage
collection 
threat can reach code that is still executed by application threads. How
do you think about this?

I've build a simple test application to reproduce the behavior. I can
post it 
to this list if there is some interest.

Thanks for your attention.

Ralf

-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys-and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
_______________________________________________
Firebird-net-provider mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/firebird-net-provider

Reply via email to