DBCP is out of date and not production grade. Some time back we conducted an in-house analysis of the two, creating a test fixture which generated load and concurrency against the two to assess their suitability under real life conditions.
DBCP consistently generated exceptions into our test application and struggled to reach levels of performance which C3P0 was more than capable of handling without any exceptions.
C3P0 also robustly handled DB disconnects and transparent reconnects on resume whereas DBCP never recovered connections if the link was taken out from beneath it. Worse still DBCP was returning Connection objects to the application for which the underlying transport had broken.
Since then we have used C3P0 in 4 major heavy-load consumer web apps and have never looked back.
UPDATE: It turns out that after many years of sitting on a shelf, the Apache Commons folk have taken DBCP out of dormancy and it is now, once again, an actively developed project. Thus my original post may be out of date.
That being said, I haven't yet experienced this new upgraded library's performance, nor heard of it being de-facto in any recent app framework, yet.
It helps to remember that both connection pooling and prepared (compiled) statements are just tools that have their limits and no approach can be equally suitable to all possible situations. With this in mind, let's remember when one might want to use connection pooling and prepared statements.
Possible Reasons to Use Connection Pooling
Connection pooling is useful when connections are expensive, for example:
- It takes significant time to establish a connection (network connections to a SQL Server or Oracle DB) and it is beneficial to "cache" open connections in an attempt to improve system performance.
- Connections are limited and shared within an application (connections from a web application serving multiple concurrent requests) or between applications so they have to be released as soon as possible to let the other clients continue.
Possible Reasons to Use Prepared Statements
Prepared statements are simply meant to improve performance of re-usable queries by cutting down the parsing time.
SQLite: What's the Best Choice?
The answer depends on your application requirements. Personally, I'm not sure if SQLite connection pooling is necessarily a good choice. If your application is single-threaded, it might be best to use a single permanent connection to the SQLite DB, which could be much faster than pooling and would allow you to use prepared statements too. This is different from SQL Server where connection pooling is a very reasonable default.
If performance matters, you should definitely profile the application to see if the SQLite connection pooling is beneficial for your scenario.
Specific Questions
Most of the answers are related to the current System.Data.SQLite
provider source.
If I am opening and closing my connection (which may or may not mean
the connection is being closed due to the thread pool) then how much
use am I really getting from a prepared statement?
Generally, you should treat a connection coming out of the pool as new, i.e. you should not expect to get any benefit from statements prepared previously. The statement will be "re-prepared" unless you keep both the command and connection.
However I don't believe I would see a benefit from saving a single
object in a transaction because once I close the connection the
prepared statement that was generated from the first object is now
lost. Is this a true statement?
This is a true statement.
If I create a SQLiteCommand that represents a query that I will be
executing often do I need to keep that SQLiteCommand in memory for the
prepared statement to stay active?
Yes, you need to keep it. SQLiteCommand
holds a reference to the prepared statement.
If I create a new SQLiteCommand with the same SQLite statement is it
recognized that the new SQLiteCommand is the same as the previous and
thus has a prepared statement that can be used?
I don't think it's supported.
If I keep a SQLiteCommand in memory and change it's parameters and
connection as I open and close the connection for different
transactions am I essentially keeping a prepared statement alive
between different connections?
If you change the SQLiteCommand
's connection, the statement will be "re-prepared".
Best Answer
Absolutely. It's possible that the
Statement
implementation will have other resources which should be released, or have some other relationship with the connection. You don't, and shouldn't, know the implementation details.Your approach is absolutely right: code to the interface and avoid little "short-cuts" which could easily bite you later. (Even if it works now, it might not in a future version of the pool or connection classes.)