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
