C# Data Connections Best Practice? - c#

Ok, so this is one of those kind of opinionated topics, but based on your knowledge, opinion, and current practice, what is the best way to set the following scenario up?
I'm building an extensive data entry application, and by extensive I mean I've only got the basics setup which incorporates around 15-25% of the overall program and I have about 15 forms that are partially setup. (They still need work) I'm using SQL Compact 4.0 as my backend database, I don't really need a more expansive database as I'm not storing an MMO's worth of data, and for the moment this is only a local application.
I would love to be able to set it up to be displayed as a single window that just changes to various different pages based on a menu system, but I can't seem to find a good tutorial on how that would be accomplished, so if anyone knows of any, please enlighten me.
The scenario in question however, is how to connect to the databases. I'm using 2 SQLCE databases, one that stores constant data that is based on services and staff, and a second that stores the constantly changing data or new data that's entered based on the first database. I have seen many different methods on how to set this up and currently I am using one in which I have a BaseForm that all other forms inherit from. Within the BaseForm I have methods and variables that are common to many forms thus minimizing the amount of code that is being repeated.
This includes the connection strings to both databases, and 2 methods that open a connection to either of them. Like so:
internal SqlCeConnection dataConn = new SqlCeConnection(#"Data Source = |DataDirectory|\opi_data.sdf");
internal SqlCeConnection logConn = new SqlCeConnection(#"Data Source = |DataDirectory|\opi_logs.sdf");
internal SqlCeCommand command;
internal void openDataConnection() // Opens a connection to the data tables
{
try
{
if(dataConn.State == ConnectionState.Closed)
dataConn.Open();
}
catch(SqlCeException ex)
{
MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
internal void openLogConnection() // Opens a connection to the log tables
{
try
{
if(logConn.State == ConnectionState.Closed)
logConn.Open();
}
catch (SqlCeException ex)
{
MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
Then whenever I need an open connection I simply call the open connection method that corresponds to the database I need access to and then close it in a finally statement. In this way a connection is never open for very long, just when it's needed. Of course this means there are a lot of calls to the open connection methods. So is this the best way to implement this sort of scenario, or are there better ways?
Is it better to just open a connection as soon as a form loads and then close it when the form closes? I have instances where multiple forms are open at a time and each one would probably need an open connection to the databases so if one closes it then the others would be screwed right? Or should I open a connection to both databases upon the application launching? Any input would be appreciated. Thanks.

Connections are pooled by .NET, so re-creating them generally isn't an expensive operation. Keeping connections open for long periods of time, however, can cause issues.
Most "best practices" tell us to open connections as late as possible (right before executing any SQL) and closing them as soon as possible (right after the last bit of data has been extracted).
An effective way of doing this automatically is with using statements:
using (SqlConnection conn = new SqlConnection(...))
{
using(SqlCommand cmd = new SqlCommand(..., conn))
{
conn.Open();
using(DataReader dr = cmd.ExecuteReader()) // or load a DataTable, ExecuteScalar, etc.
{
...
{
}
}
That way, the resources are closed and disposed of even if an exception is thrown.
In short, opening a connection when the app opens or when each form opens is probably not the best approach.

Related

Usage of mysqlconnection in C# [duplicate]

Ok, so this is one of those kind of opinionated topics, but based on your knowledge, opinion, and current practice, what is the best way to set the following scenario up?
I'm building an extensive data entry application, and by extensive I mean I've only got the basics setup which incorporates around 15-25% of the overall program and I have about 15 forms that are partially setup. (They still need work) I'm using SQL Compact 4.0 as my backend database, I don't really need a more expansive database as I'm not storing an MMO's worth of data, and for the moment this is only a local application.
I would love to be able to set it up to be displayed as a single window that just changes to various different pages based on a menu system, but I can't seem to find a good tutorial on how that would be accomplished, so if anyone knows of any, please enlighten me.
The scenario in question however, is how to connect to the databases. I'm using 2 SQLCE databases, one that stores constant data that is based on services and staff, and a second that stores the constantly changing data or new data that's entered based on the first database. I have seen many different methods on how to set this up and currently I am using one in which I have a BaseForm that all other forms inherit from. Within the BaseForm I have methods and variables that are common to many forms thus minimizing the amount of code that is being repeated.
This includes the connection strings to both databases, and 2 methods that open a connection to either of them. Like so:
internal SqlCeConnection dataConn = new SqlCeConnection(#"Data Source = |DataDirectory|\opi_data.sdf");
internal SqlCeConnection logConn = new SqlCeConnection(#"Data Source = |DataDirectory|\opi_logs.sdf");
internal SqlCeCommand command;
internal void openDataConnection() // Opens a connection to the data tables
{
try
{
if(dataConn.State == ConnectionState.Closed)
dataConn.Open();
}
catch(SqlCeException ex)
{
MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
internal void openLogConnection() // Opens a connection to the log tables
{
try
{
if(logConn.State == ConnectionState.Closed)
logConn.Open();
}
catch (SqlCeException ex)
{
MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
Then whenever I need an open connection I simply call the open connection method that corresponds to the database I need access to and then close it in a finally statement. In this way a connection is never open for very long, just when it's needed. Of course this means there are a lot of calls to the open connection methods. So is this the best way to implement this sort of scenario, or are there better ways?
Is it better to just open a connection as soon as a form loads and then close it when the form closes? I have instances where multiple forms are open at a time and each one would probably need an open connection to the databases so if one closes it then the others would be screwed right? Or should I open a connection to both databases upon the application launching? Any input would be appreciated. Thanks.
Connections are pooled by .NET, so re-creating them generally isn't an expensive operation. Keeping connections open for long periods of time, however, can cause issues.
Most "best practices" tell us to open connections as late as possible (right before executing any SQL) and closing them as soon as possible (right after the last bit of data has been extracted).
An effective way of doing this automatically is with using statements:
using (SqlConnection conn = new SqlConnection(...))
{
using(SqlCommand cmd = new SqlCommand(..., conn))
{
conn.Open();
using(DataReader dr = cmd.ExecuteReader()) // or load a DataTable, ExecuteScalar, etc.
{
...
{
}
}
That way, the resources are closed and disposed of even if an exception is thrown.
In short, opening a connection when the app opens or when each form opens is probably not the best approach.

Why do we need to create, open and close db connections to retrieve multiple result sets but not if retrieving one set?

In order to retrieve different result sets being returned by the stored procedure we have to use this:
UsersPhonesDBContext.Database.Initialize(force: false);
DbConnection con = UsersPhonesDBContext.Database.Connection;
var cmd = con.CreateCommand();
cmd.CommandText = "[dbo].[SelectPhones]";
con.Open();
var reader = cmd.ExecuteReader();
Phones phones = ((IObjectContextAdapter)UsersPhonesDBContext)
.ObjectContext
.Translate<Phones>(reader, "Phones", MergeOption.AppendOnly).First();
reader.NextResult();
Users users = ((IObjectContextAdapter)UsersPhonesDBContext)
.ObjectContext
.Translate<Users>(reader, "Users", MergeOption.AppendOnly).First();
But if the procedure is returning a single result set then we can simply do that with
var phones1 = UsersPhonesDBContext.Database.SqlQuery<Phones>("dbo.InsertPhones #model", sqlParam);
without creating, opening and closing DB connection etc.
So my question is that why do we have to create & open connections if multiple sets but not for the single since both are accessed from the database.
Opening and close database connections are expensive operations in terms of time and resources. At the same time if the connection is left open for long time it might cause a memory leak or security risk.
So the recommended approach is to open database connection only when needed and close as soon as the purpose of opening it is served.
In the example you shared, there are multiple database operations happening in one go. So instead of opening connection individually for every operation, only one connection is opened and it is close after the operation are done. Here connection is opened and close manually.
The new approaches of DataAccess Layers such as EntityFramework etc does this job internally.
UsersPhonesDBContext.Database.SqlQuery<Phones>("dbo.InsertPhones #model", sqlParam);
In this line of code, the connection to database is opened and close internally without us worrying about it.
So the main motive is to minimize the connection open and close operations and close the connection as soon as the purpose of opening it is over.

SQL Connection Time out issue

I have web application which contains the class to connect sql server. I have written the connection class like below
public SqlConnection DbConnectSql()
{
string str = System.Configuration.ConfigurationManager.ConnectionStrings["conStr"].ToString();
_con = new SqlConnection(str);
if (_con.State == ConnectionState.Open)
_con.Close();
_con.Open();
return _con;
}
When I am using the above code on the production server, some times the connection is not getting opened. The connection works fine after restarting the IIS. I have to do the IIS restart every two days. to work the sql connection. We didn’t get the exact exception of this issue.
To solve this, do we need to close the connection for all other cases except “_con.State == ConnectionState.Closed”? If we do so, is there any after affect for this code?
Modify
if (_con.State == ConnectionState.Open)
_con.Close();
_con.Open();
in
if (_con.State == ConnectionState.Closed)
_con.Open();
and try.
Usually it's not good practice to check if a connection is open when you start it then close it immediately and reopen it immediately as there could be latency issues.
It makes much more sense to check if there is any connection open with that session (connection == Connection.Closed) and then, if it's closed, open it, else do nothing because I am already connected.
This way, beyond being more logically meaningful is also more concise.
Also, in your code, when you use your SqlConnection, wrap them in a
using(_con)
{
//code here, sql stuff
};
statement, as it will manage itself all the closing and disposing connection stuff so you are sure when your sql logic is done everything gets disposed correctly without having to call Close and Dispose methods manually.
Let me know if it worked.
do we need to close the connection for all other cases
Sure, simply because all connections are created in a single Pool. See https://learn.microsoft.com/en-us/dotnet/framework/data/adonet/sql-server-connection-pooling
Try to minimize connection creations (or reusing existing ones)
After finish usage of it, call con.Close() then con.Dispose() to insure you free resources

What is Best Approach for Opening/Closing SqlConnection in C#

I would like to know what could be best approach to open a SqlConnection with Sql Server 2008R2 Express Edition Database. This Version of Sql has Limitations of RAM Usage and CPU Usage so we must adopt something best to open a SqlConnection.
Right Now i am Checking Connection on Start and End of each and every Method. Here is an example of that.
private void CheckValidId(string Id)
{
CheckConnectionStatus();
try
{
sqlConnection.Open();
sqlCommand = new SqlCommand("select * from ValidId where id=#id", sqlConnection);
sqlCommand.Parameters.AddWithValue("#id", Id);
sqlDataReader = sqlCommand.ExecuteReader();
While (sqlDataReader.Read())
{
string Test = sqlDataReader["Id"].toString();
MessageBox.Show("Value of Id : " , Test);
}
}
catch (Exception exp)
{
MessageBox.Show(exp.Message.ToString(), "Exception in CheckValidId");
}
finally
{
CheckConnectionStatus();
}
}
Here is CheckConnectionStatus Method
private void CheckConnectionStatus()
{
if (sqlConnection.State == ConnectionState.Open)
{
sqlConnection.Close();
}
}
What is best approach to perform this operation.
Thanks
Just use using as it disposes of the connection once done.
using(SqlConnection conn = new SqlConnection("Connection string")){
//do sql stuff
conn.Open();
//etc etc
conn.Close();
}
You'll want to make use of the disposable pattern to ensure everything is closed and disposed properly:
var query = "select * from ValidId where id=#id";
using (var conn = new System.Data.SqlClient.SqlConnection(usingConnectionString))
using (var command = new System.Data.SqlClient.SqlCommand(query, conn))
{
command.Parameters.Add("#id", SqlDbType.Int).Value = Id;
conn.Open;
using (var reader = command.ExecuteReader())
{
while (reader.Read())
{
string Test = reader["Id"].ToString();
}
}
command.Parameters.Clear();
}
You don't need to check the connection state; it will close when it's being disposed.
One thing to note: it's best practice to explicitly specify your parameter data types. I've assumed SqlDbType.Int in your case, but you can change it to whatever it really is.
Another thing to note: you don't want to do too much inside the reader while loop. You want to build your collection or whatever and get out of there. The shorter your connection is open, the better. That's because you could potentially be holding a read lock on some of the rows in the database that might affect other users and their applications.
Your pattern for open and close is correct. However you must note that this doesn't open and close the connection to the SQL Server so doesn't really address your concerns over memory usage and CPU - in fact it wont make any difference.
What Open and Close does is lease and return a connection to the ADO Connection Pool on the client PC. This means that Closing an ADO connection is not guaranteed (and in most cases will not) close and release the connection to the SQL Server. This is becasue establishing and authenticating a connection is relatively expensive and slow, so the ADO connection pool keeps your connections in a pool, still open, just in case you want to re-establish a connection.
What makes the difference to SQL Server is the number of concurrent queries it needs to execute - and the dataset size of the queries, and the total size of the data in the database.
Concurrent queries squeeze CPU, and the datasets returned squeeze the RAM available. Obviously the bigger your database the less can be cached in RAM and so the less likely you are to get a cache hit when querying.
In practice my experience with SQL Express editions is that you wont notice any difference between it and the full edition of SQL Server unless you are doing some very specific things;
1) Writing a BI style tool which allows the user to construct user-defined or user-scoped queries.
2) Writing terrible SQL - "big SQL" may mask your bad query syntax, but Express wont be able to because it has less available RAM to play with.
If you write efficient, constrained SQL, you probably wont actually ever hit any of SQL Express's limitations.

Database timeout

I have a program that access database and excecute different methods that have a database call.
I have used one conenction for everything but it caused a timeout while executing a long task:
I basically had to go through the more than 6000 records and execute a stored procedure. I thing that caused a timeout since I used only one database connection for everything.
Then I changed the code, so I open and closing the connection for every method I call with "using" approach.
How should I handle the method that will be called a lot. Shouls I open/close connection everytime I access that method?
Or there is a different approach to it?
I do something like this:
foreach(record in MyCollection)//6000
{
using(connection = new SqlConnection(conString))
{
singledata = GetSingleData(record);
}
}
Here is a GetSingleData()
private byte[] GetSingleData(MyObject Data)
{
byte[] singleData = null;
using(SqlCommans......)
{
try
{
.......
//executing stored proc to get just a single row
reader = command.ExecuteReader();
while(reader.Read())
{
singleData = (byte[])reader["ColumnName"];
}
}
catch(SqlException ex)
{
if(!reader.isClosed)
reader.Close();
}
}
return singleData;
}
Is it efficient or I can set up some kind of counter and for each 500 records I can check if connection is closed and if it is then reopen it.
Thank's
Try using a persistent connection. Here's a post that might help if you want to try to tune your system (for MySQL):
http://www.mysqlperformanceblog.com/2011/04/19/mysql-connection-timeouts/
Hope that helps.
There is no such a thing as the only good way to do something. It all depends. In cases where agility is a must and you need to create ad-hoc solutions, opening and closing a connection in each method call might not be good theoretically, but accepted practically.
I urge you to read about these terms and concepts:
Connection pooling
Bulk operations (bulk update, bulk insert)
They might help you in getting more performance.

Categories