Managing SQL Server Connections - c#

What is the the best practice for SQL connections?
Currently I am using the following:
using (SqlConnection sqlConn = new SqlConnection(CONNECTIONSTRING))
{
sqlConn.Open();
// DB CODE GOES HERE
}
I have read that this is a very effective way of doing SQL connections. By default the SQL pooling is active, so how I understand it is that when the using code ends the SqlConnection object is closed and disposed but the actual connection to the DB is put in the SQL connection pool. Am i wrong about this?

That's most of it. Some additional points to consider:
Where do you get your connection string? You don't want that hard-coded all over the place and you may need to secure it.
You often have other objects to create as well before your really use the connection (SqlCommand, SqlParameter, DataSet, SqlDataAdapter), and you want to wait as long as possible to open the connection. The full pattern needs to account for that.
You want to make sure your database access is forced into it's own data layer class or assembly. So a common thing to do is express this as a private function call:
.
private static string connectionString = "load from encrypted config file";
private SqlConnection getConnection()
{
return new SqlConnection(connectionString);
}
And then write your sample like this:
using (SqlConnection sqlConn = getConnection())
{
// create command and add parameters
// open the connection
sqlConn.Open();
// run the command
}
That sample can only exist in your data access class. An alternative is to mark it internal and spread the data layer over an entire assembly. The main thing is that a clean separation of your database code is strictly enforced.
A real implementation might look like this:
public IEnumerable<IDataRecord> GetSomeData(string filter)
{
string sql = "SELECT * FROM [SomeTable] WHERE [SomeColumn] LIKE #Filter + '%'";
using (SqlConnection cn = getConnection())
using (SqlCommand cmd = new SqlCommand(sql, cn))
{
cmd.Parameters.Add("#Filter", SqlDbType.NVarChar, 255).Value = filter;
cn.Open();
using (IDataReader rdr = cmd.ExecuteReader())
{
while (rdr.Read())
{
yield return (IDataRecord)rdr;
}
}
}
}
Notice that I was also able to "stack" the creation of the cn and cmd objects, and thus reduce nesting and only create one scope block.
Finally, a word of caution about using the yield return code in this specific sample. If you call the method and don't complete your DataBinding or other use right away it could hold the connection open for a long time. An example of this is using it to set a data source in the Load event of an ASP.NET page. Since the actual data binding event won't occur until later you could hold the connection open much longer than needed.

Microsoft's Patterns and Practices libraries are an excellent approach to handling database connectivity. The libraries encapsulate most of the mechanisms involved with opening a connection, which in turn will make your life easier.

Your understanding of using is correct, and that method of usage is the recommended way of doing so. You can also call close in your code as well.

Also : Open late, close early.
Don't open the connection until there are no more steps left before calling the database. And close the connection as soon as you're done.

Related

how to properly create a postgres database connection class in c#?

I am new to working with databases.I am using postgres database.I want to connect it to c# for my project.Since I have multiple form screen in my project, I assume it is better to create a seperate database connection class instead of using the same code in every other classes.I want to learn how to create an effective postgres database connection class in c#
There's no need to create a connection class since database connections and commands aren't complicated or expensive to create. The best practice is to create a connection and command, execute the SQL, and then dispose of both of them. The typical pattern is:
string connString = {connection string from config};
using (OdbcConnection conn = new OdbcConnection(connString)) {
using(OdbcCommand cmd = new OdbcCommand(sql, conn) {
// execute command
}
}
The using construct ensures that the connection and command are closed een if there is a database error.
Take a look at this website: https://www.connectionstrings.com/postgresql/
This is a great resource for finding connection strings to a variety of different databases! I reference it quite a bit. There are a couple of different connection strings for postgreSql, so you will need to dtermine which one is best to use for your use case.
I wouldn't set up a special class for a connection. Instead I recommend that you use an appsettings.json or web.config file to store the connection string and call it when you need it. Check out the documentation from Microsoft: https://learn.microsoft.com/en-us/aspnet/core/fundamentals/configuration/?view=aspnetcore-6.0

Calling a linked server fails after a snapshot connection has been disposed

We have a C# application using ADO.NET and an SQL-Server with SNAPSHOT Transaction Isolation Level. This is 'as is' and unfortunately cannot be modified.
Now we need insert stuff on a linked server.
We execute the following code (reduced to illustrate the problem):
// Create a snapshot Transaction and close the connection
using (var con = new SqlConnection(myConStr))
{
con.BeginTransaction(TransactionLevel.Snapshot);
}
// do something with a linked server
using (var con = new SqlConnection(myConStr))
{
using (var cmd = con.CreateCommand()
{
cmd.CommandText = "insert into LinkedServer.SomeDb..Table ...";
cmd.ExecuteNonQuery();
}
}
We get can an exception when trying to insert something into the linked server
'Remote access is not supported for transaction isolation level "SNAPSHOT"'
I wonder why it is not possible: We open the connection, make sure it is disposed (clearing all transactions, I guess) and use a second connection for the linked server call.
Executing the stuff in SSMS using plain SQL seems to work.
What are we missing? Is there a proper way to do it?
Thanks for any hints in the right direction.
The secret to understand the problem is the 'connection pooling' which is done by ADO.NET in the Background. The real connection is actually set to SNAPSHOT.
In the second part of the sample code, that connection simply gets reused thus still being in 'snapshot mode'.
The solution is to explicitly set the transaction isolation Level to something else right after opening the Connection.
using (var con = new SqlConnection(myConStr))
{
using (var cmd = con.CreateCommand()
{
cmd.CommandText = "set transaction isolation Level read committed";
cmd.ExecuteNonQuery();
}
using (var cmd = con.CreateCommand()
{
cmd.CommandText = "insert into LinkedServer.SomeDb..Table ...";
cmd.ExecuteNonQuery();
}
}

how to use mysqlconnection throughout the application

I am trying to have a MySQL connection open in the main form. However, O am having trouble trying use the connection in other forms.
How should I set it up so that I only need to open the connection once in the whole program, and use the same connection to get data from database.
Or should I have a new connection open in each form?
Thank you
It is better to use using statement with SQL connection as follow:
using (SqlConnection connection = new SqlConnection(connectionString))
{
//Your code goes here
}
and make the connection string in App.config file.
You don't want to just leave a connection open the whole time the app is running. It's better to create a single function that you can call repeatedly if your goal is to simplify code readability. The below example is as basic as it gets, but you'll need to do a bit more for stored procedures and Parameter objects not in a query string. All this will do is fill a datatable.
public DataTable RunQuery(string query)
{
//connectionString should come from your configuration or a constant that is a part of this class
DataTable dt = new DataTable();
using (SqlCommand cmd = new SqlConnection(connectionString))
{
cmd.CommandText = query;
cmd.Connection.Open();
using (SqlDataAdapter sda = new SqlDataAdapter(cmd))
{
sda.Fill(dt);
}
cmd.Connection.Close();
}
return dt;
}
Calling it is easy.
RunQuery("Select * from myData");
Basically, you have to open your MySqlConnection once, and then reuse your connection with using, or by checking it´s state. It is the same as every ADO.NET library. Using the usingstatement you have guarantee that the object will be disposed and all resources released.
This link has everithing you need about working with MySql: https://www.codeproject.com/Articles/43438/Connect-C-to-MySQL

c# : one class to connect to sql server

Hello there I hope you're having a great time.
I have a question And I will break it down into 3 points:
1: create a class to connect to sql server the connection should be made using sql server authentication.
This class should contain several variables for connection parameters.
2: create a user form that shows the current connection parameters. And allow the user to update those parameters. In this form there should be a button to test the connect and another button to save the user changes to the connection parameters.
3: how to share the connection, created by the class we made in point 1, between different forms in the application. Without keeping too many open connections ideally only one connection should be open.
I will add the code that can solve this problem I hope that you can help me refine it.
I am new to all of this.
Thank you all for help.
already exists; SqlConnection and maybe SqlConnectionStringBuilder
that kinda already exists, via the IDE, but last time I checked this was not a redistributable dll. You could, however, simply hook a SqlConnectionStringBuilder to a PropertyGrid - or just write the UI from scratch
even "only one connection should be open" is wrong, IMO - let the inbuilt connection pooling deal with that; all you need is some configuration class with the connection string - and just deal with the connections as you need them, very locally - i.e.
using(var conn = new SqlConnection(Config.ConnectionString))
{
conn.Open();
// NOT SHOWN: do a couple of related operations
} // <== and here, it dies
1 : go to MSDN website you'll find what you need :
http://msdn.microsoft.com/fr-fr/library/system.data.sqlclient.sqlcommand.aspx?cs-save-lang=1&cs-lang=csharp#code-snippet-2
private static void ReadOrderData(string connectionString)
{
string queryString =
"SELECT OrderID, CustomerID FROM dbo.Orders;";
using (SqlConnection connection = new SqlConnection(
connectionString))
{
SqlCommand command = new SqlCommand(
queryString, connection);
connection.Open();
SqlDataReader reader = command.ExecuteReader();
try
{
while (reader.Read())
{
Console.WriteLine(String.Format("{0}, {1}",
reader[0], reader[1]));
}
}
finally
{
// Always call Close when done reading.
reader.Close();
}
}
}
2: look at your connection properties (http://msdn.microsoft.com/en-us/library/System.Data.SqlClient.SqlConnection_properties.aspx) and fill a listView or equivalent with it
3: Use previous SqlConnection.Open() to deal with it

C# DbConnection cast to SqlConnection

I found this piece of code in one application
Database database = DatabaseFactory.CreateDatabase("connection string");
DbConnection connection = database.CreateConnection();
connection.Open();
SqlConnection sqlConnection = (SqlConnection)connection;
Is it safe, SqlConnection derieve from DbConnection. Database comes from Microsoft.Practices.EnterpriseLibrary.Data. According to documentation CreteDatabase returns DbConnection.
No it is not safe, casting is never safe and it may blow anytime while your application is running. While SqlConnection derives indeed from DbConnection you are not guaranteed that database.CreateConnection() will return a SqlConnection as this could be parametrized in the configuration file. Also why do you need to cast to SqlConnection? It is always better to work with classes that are higher in the hierarchy to avoid coupling your code with a specific implementation which will make your code impossible to test in isolation.
While the EnterpriseLibrary does a decently good job in keeping things abstract you are killing everything with this cast. Also you should make sure that disposable resources are always disposed properly. How about this instead:
Database database = DatabaseFactory.CreateDatabase("connection string");
using (var conn = database.CreateConnection())
using (var cmd = conn.CreateCommand())
{
conn.Open();
cmd.CommandText = "SELECT id FROM foo";
using (var reader = cmd.ExecuteReader())
{
while (reader.Read())
{
// TODO: work with the results here
}
}
}
This way your code is less fragile to database changes in the config file. Well of course you still have this SQL hardcoded and there are ORMs that will take care of this situation. They will also allow you to focus on the real domain of your application instead of wasting time in writing SQL queries and casting from one database provider to another. But for a simple application this is OK.
It should be safe as long as you never change the connection string to connect to anything other than a SQL Server Database. If that's ever a possibility, then you should add a little more logic to make things safe:
Database database = DatabaseFactory.CreateDatabase("conn string");
using(DbConnection conn = database.CreateConnection())
{
if(conn is SqlConnection)
{
var sqlConn = conn as SqlConnection;
}
}
It depends on the databases you are using in your application. From the code you wrote it looks like that only SQL Server is used. If it is so, then you can cast DbConnection to SqlConnection safely. In fact DbConnection is a base class for any other database connection. In your case it is SqlConnection (which is used to work with SQL Server database), also there are different databases like Oracle, Mysql, etc and their providers usually have own classes for connections. So if your app uses another databases or may use in the future it is unsafe to have such cast.
You can always do a check and convert it to SqlConnection with C# pattern matching (C# 7.0+)
Database database = DatabaseFactory.CreateDatabase("conn string");
using(DbConnection connection = database.CreateConnection())
{
if(connection is SqlConnection sqlConnection)
{
// do something with sqlConnection
}
else
{
throw new InvalidOperationException("Connection is not to a SQL Database");
}
}

Categories

Resources