What would be a good way to writein C# a .NET3.5 Thread Safe DataSource Class. The class would connect to SQL Server and every method would execute a Stored Procedure.
When the code worked single threaded. I had a Singleton DataSource Class with a private SqlConnection member. Each method opened and closed that connection. When running this with multiple threads it is causing trouble when under certain scenarios the connection has already been opened by another thread. What would be the best way to re-write this class?
Note: By DataSource dont mean any built in .NET class, but a Model class that provides data to the controller.
Why don't you just use built-in ado.net pooling: create and open the connection right before the operation and dispose is asap - for every method.
The problem seems to be from the Singleton design. That can still work, just make sure you do not store the connection as a field. Only use a local variable in each method to hold the connection. That should be thread-safe by design.
And make it Exception-safe as well:
using (var conn = new SqlConnection(...))
{
// call SP
}
SQL Server already coordinates threads through very complex mechanisms. You don't need to do anything specific to achieve thread safety to simply execute a Store Procedure.
You'd have to elaborate more about what your DataSource class should do. You don't need to implement any thread safety code if each of your Create/Read/Update/Delete methods do not alter any state.
UPDATE: In your case, I recommend to just recreate a new SqlConnection instance in every method of your DataSource class, because ADO.NET already handles the pooling for you.
Related
I am writing c# wrapper class for MySQL and I need to know if I can put a "new MySqlConnection(connstr)" into the constructor and then use the same object between the methods that are going to manipulate the database? Should I create a new connection for every operation (select, insert, delete, update) and destroy it when done. Any ideas or better approaches to write a MySQL wrapper?
I'd recommend not sharing that connection.
It won't scale as well as getting that connection out from a pool when it's needed, performing the SQL operation, closing resources, and then returning the connection to the pool.
I consider it a best practice to restrict SQL objects to the data access layer and using them in the narrowest scope possible. Don't pass them around - the responsibility for cleaning them up isn't clear if you do.
Connections ought to be owned by the service that knows about use cases, units of work, and transactions. Let it check out the connection, make it available to all DAOs that need it, then commit or rollback and close the connection.
DAOs should be given database connections. They should not acquire them on their own, because they can never know if they're part of a larger transaction or not.
For database connection the rule should be Open as Late as possible and close as early as possible,.
So open the connection before executing the query and then close it, rather than sharing a single connection object across different methods.
There is a MySqlHelper class that should do all your connection pooling, opening, closing, disposing, etc for you. "These take a connection string as an argument, and they fully support connection pooling." That is only is you are using the Oracle provided MySQL connector though.
So I am finding myself struggling which is the best practice. This is my first time coding C# and first time coding anything in like a decade. Back when I worked as a php / sql programmer, we usually frowned on the idea of opening a new connection for every query, but the more I research this question on google today, specifically with C# and sqlite, the more it seems many recommend doing the polar opposite.
So, I was hoping the put this question out for some of you guys, who have obviously been doing this a lot more than eye. Here is the general setup of my database class:
class DatabaseController
{
static private SQLiteConnection _sqlconn;
static private string _uri;
public static SQLiteConnection Sqlconn
{
get { return DatabaseController._sqlconn; }
set { DatabaseController._sqlconn = value; }
}
public static string Uri
{
get { return DatabaseController._uri; }
set { DatabaseController._uri = value; }
}
}
The second class, which is the main Database class, which deals with actually running queries and such. The reason I have the DatabaseController class is because I can store the open connection handle to the static member _sqlconn and so the connection is only ever opened once, and Database objects simply use the same handle, even though the program can and will create many Database objects.
But again, is this actually necessary? Should I simply be opening a new connection within the main Database class, every time an object is created? There was another site and thread I found that apparently, what the .NET Framework does is even though you maintains a connection pool for you, so even though you might be opening and disposing of several connections, they aren't truly closed. Is this truly so, and does that apply to both desktop and windows 8 apps?
It is recommended to keep connections 'open' only for as long as they are needed i.e. as long as the unit of work requires.
As you have suggested, when you 'close' them they are not actually closed, but just returned to the pool for re-use by other threads/applications. This applies to any ADO.NET data provider.
If your application is single threaded, then you probably won't notice pooling occurring, but in situations when there are many threads requiring data-access then the quicker connections are returned to the pool then the quicker they can be re-used by other threads.
When using sqlite you have to know how the engine was compiled. See here http://sqlite.org/threadsafe.html. It's important since sqlite behaves differently depending on the threading model used.
You might have to have logic where the connection is shared between all code that want to access the databse. You might also need code which prevents different threads from working with the Sqlite db simultaneously.
Most other ADO.NET providers supports connection pooling which means that the connections are reused when you invoke the Close() method.
I have a GUI where different parts of the information shown is extracted from a database. In order for the GUI not to freeze up I've tried putting the database queries in BackgroundWorkers. Because these access the database asynchronously I get an exception telling me the database connection is already open and used by another.
Is it possible to create a queue for database access?
I've looked into Task and ContinueWith, but since i code against .Net framework 3.5 this is not an option.
What is the DB engine you're using? Most modern databases are optimized for concurrent operations, so there's no need to queue anything.
The thing you're appaently doing wrong is reusing the same IDbConnection instance across different threads. Thats a no-no: each thread has to have its own instance.
I think your problem is in the way you get a connection to the database. If you want to fire separate queries you could use separate connections for separate requests. If you enable connection pooling this does not add a lot of overhead.
Try to use the pool objects. Plus as per your description your trying to open a connection on an unclosed connection object.
I'm currently writing a Windows Service that will run on a Windows Server 2008.
My colleague and I were discussing on one point particular. The connection to the database.
We both have a different way in mind and we would like to know your opinions on it.
Basicly the service starts a thread that sends a query to the database to check on rows that have a certain status (for example ST005). All rows with that status will be returned. The data we receive will be processed and the rows will be updated in the end.
So basicly we once execute a query and then for each row we execute an update. Multiple threads can be running at the same time. There is no problem with the coding, but it's the structure we don't really seem to agree on.
The classes we have are a controller, a DAO and a database class.
Way #1:
The controller creates a DAO class to process a query. That DAO class builds the sql statement with its parameters and then creates a database class which opens the connection, executes the query, returns the result set and then closes the connection.
This way there will be a new connection each time a query or update is requested.
Way #2:
The controller creates a database class (the database class is now provided with two new methods, connect() and disconnect(). Then the controller calls upon the connect() statement and creates a DAO class and provides the database class as parameter for the constructor of the DB class. The DAO class builds the sql statement with its parameters and then processes the data.
This way there is only one database class during the whole lifetime of the thread. During the whole thread the same connection is opened and only closed near the end of the threads lifetime.
What way is the best to use here? It seems like having multiple connections seems to be a bad practise, or are we wrong here? Any insight on this will be appreciated.
Regards,
Floris
Use a connection pool, as almost certainly is provided by your DBMS vendor, and let it figure out the best strategy. Ends the discussion.
I've got a winform with some child forms on it. Now I'm accessing the child forms by a treeview in my main form. Now in that treeview is a list of websites. Since a website is actually a group of pages, this is also shown in the tree. Website is my parent and the pages are the childs.
When you click on one of the pages the statistics are shown in a child form. When clicked on a website a summary of all pages is shown of that website. Since this can have a lot of data I'm using a background worker that fetches the statics in the background after the treeview is loaded.
Now all fine until I'm changing something in the statistics and it saves automatically into the database (sqlserver2008). Then my backgroundworker generates errors saying the sqlreader is closed. So I'm wondering how I can solve this.
Do I have to access the database on a separate connection? Any other ideas?
Thanks
Are you using the same database connection object on several threads? That's not safe. Every thread must have its own database connection, or it must synchronize the usage so that only one thread accesses the database connection object at any given moment.
It sounds like your UPDATE is closing the connection and your background thread is attempting to use it to query. If im reading between the lines correctly, you have created a connection object as a stateful member of your winform which is being opened once and possibly being closed after an UPDATE (or automatically by the connection pool). Either way you need to take a step back here and think about how your doing things.
Your update and select methods (hopefully in separate classes to your forms) should take care of opening and closing connections exclusively rather than in a statefull way (i.e. the scope of the connection remains in the methods). The ADO connection pool will take care of optimising connections for you.
I also recommend you use disconnected data structures such as DataTable and DataSet rather than DataReader as these keep the connection footprint between the client and the database light. You can happily process and pass around these structures without maintaining an open connection which DataReader requires. Ideally you would populate a light-weight object structure rather than passing DataSet around too much as it does carry some memory overhead - there are a bunch of other reasons for this too e.g. type safety.
There is nothing wrong with calling a method which executes queries on multiple threads as long as the scope of the connection is limited to the method. For example:
public static DataSet GetWebStatsData()
{
DataSet StatsData = new DataSet();
using (OleDbConnection conn = new OleDbConnection(ConnString))
{
using (OleDbCommand cm = new OleDbCommand(GetDataProcedure))
{
using (OleDbDataAdapter adap = new OleDbDataAdapter(cm))
{
cm.Connection = conn;
conn.Open();
adap.Fill(StatsData);
conn.Close();
}
}
}
return StatsData;
}
You can happily call the above method from many threads simultaneously and it should work. I have worked on applications making heavy use of the threadpool executing in some cases scores of queries simultaneously with no ill effect. Where this is happening i would recommend setting a maximum size to the ado.net connection pool as it can grow quite large if left un-guarded (there is typically a connection string attribute for this like 'Max Pool Size=n'). Ado.net will marshal the connections on your behalf so there is a lot of plumbing to leverage in the framework here.
I would guess that the navigation event is firing off a new database request using an existing sqlcommand. Can you post up a code snip?
If you're using the same connection string you can open multiple SqlConenction/SqlCommand/SqlDataReader objects and they'll come from the connection pool. There is no reason you can't have multiple connections to the same database! You can read some more information at SQL Server Connection Pooling (ADO.NET).
If you're trying to use the same SqlConnection on multiple threads at the same time, that will definitely produce unpredictable results. Creating a connection for each thread is easiest, or you could use some form of synchronization if you really want to share a single connection. That would only make sense if your worker threads are doing a significant amount of work besides database access though.