C# DbConnection cast to SqlConnection - c#

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");
}
}

Related

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

Is it possible to connect to SQL Server without specifying a database?

I'm trying to write some unit tests for my code that connect to SQL Server for persistence, but I would like to be able to run my unit tests by just pointing it at a SQL Server instance, and let the tests create their own database to run tests in, so after each test it can just drop the database and then on setup before the next test recreate it, so I know there is no legacy data or structures left over from a previous test effecting the next test.
In brief: no, you cannot do that. You might be able to leave out the database from the connection string, but in that case, that connection will be made to the configured default database of the login that's connecting to SQL Server (and that default database must exist at the time the connection is made)
If you want to have this scenario, you need to
first connect to your instance and database master and create your new testdb (or whatever it's called)
disconnect
in your tests, connect to the instance and the testdb database
Better yet: use a mocking framework of some sort so you don't even need an actual database in your testing scenario!
I use the following class to facilitate the OP's scenario:
public class MsSqlDatabaseCreator
{
public void Create(string connectionstring)
{
if (DatabaseExists(connectionstring))
{
DropDatabase(connectionstring);
}
CreateDatabase(connectionstring);
}
private static void CreateDatabase(string connectionString)
{
var sqlConnectionStringBuilder = new SqlConnectionStringBuilder(connectionString);
var databaseName = sqlConnectionStringBuilder.InitialCatalog;
sqlConnectionStringBuilder.InitialCatalog = "master";
using (var sqlConnection = new SqlConnection(sqlConnectionStringBuilder.ConnectionString))
{
sqlConnection.Open();
using (var sqlCommand = sqlConnection.CreateCommand())
{
sqlCommand.CommandText = $"CREATE DATABASE {databaseName}";
sqlCommand.ExecuteNonQuery();
}
}
}
private static bool DatabaseExists(string connectionString)
{
var sqlConnectionStringBuilder = new SqlConnectionStringBuilder(connectionString);
var databaseName = sqlConnectionStringBuilder.InitialCatalog;
sqlConnectionStringBuilder.InitialCatalog = "master";
using (var sqlConnection = new SqlConnection(sqlConnectionStringBuilder.ConnectionString))
{
sqlConnection.Open();
using (var command = sqlConnection.CreateCommand())
{
command.CommandText = $"SELECT db_id('{databaseName}')";
return command.ExecuteScalar() != DBNull.Value;
}
}
}
private static void DropDatabase(string connectionString)
{
var sqlConnectionStringBuilder = new SqlConnectionStringBuilder(connectionString);
var databaseName = sqlConnectionStringBuilder.InitialCatalog;
sqlConnectionStringBuilder.InitialCatalog = "master";
using (var sqlConnection = new SqlConnection(sqlConnectionStringBuilder.ConnectionString))
{
sqlConnection.Open();
using (var sqlCommand = sqlConnection.CreateCommand())
{
sqlCommand.CommandText = $#"
ALTER DATABASE {databaseName} SET SINGLE_USER WITH ROLLBACK IMMEDIATE;
DROP DATABASE [{databaseName}]
";
sqlCommand.ExecuteNonQuery();
}
}
}
}
The important part is the switching of the database name (initial catalog) to master. This way you can have just one connectionstring.
What you want to accomplish is possible using a mocking framework, in which case you don't even have to "connect to a database", you simply mock the return values that the database should return in order for you to test your "db handler" implementation.
There are several to choose from when it comes to C#, I can recommend Rhino Mocks and Moq to name two. Here's a question detailing a bit more; https://stackoverflow.com/questions/37359/what-c-sharp-mocking-framework-to-use
Why not have the same named database dedicated for tests? and drop-create it every time. This way you won't need to mess about with connection strings - it is always the same.
And yet, there is a better solution: within all your tests, start transaction, do your test, where your data is messed up. Once you verified (or failed) the test, unroll the transaction. This way you don't need to drop-create your tests for every test, because the data is never changed.
But you'll need to make sure schema in test-database is always up to date. So you'll need to drop-create test database whenever your schema is changed.
I've blogged about database tests and how we deal with Entity Framework migrations. This might not be completely applicable to your situation, but might help with ideas.
Regarding using mocks in your tests - yes this is absolutely valid suggestion and should be followed most of the time. Unless you are trying to test the database layer. In that case no mocks will save you, and you just have to go to DB. Many times over I have tried to mock DbContext in EF, but never managed to simulate realistic DB behavior. So going to DB was easier for me, rather than simulating DB-mock.
I'd use SQL Server Management Objects for the task. It's Server and Database APIs doesn't necessarily need a connection string but I think you might still need to specify a database. You can use master for that. (Check jeroenh's answer about creating object using SMO API as well)
By the way, if you are using .Net 4.0.2 and up you can use LocalDB as well, which is even better.
Edit: Note that actually LocalDB is an SQL Server 2012 feature however you still need .Net Framework > 4.0.2 to be able to use it.

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

DbProviderFactory code relationship with code for creating a SqlConnection in ADO.Net

When I instantiate a SqlConnection object in ADO.Net, then does this code result in the execution of corresponding DbProviderFactory code ? So when the code in block 2 is executed by, then we actually end up executing code in block 1. But I am not sure if this is true.
CODE BLOCK 1 - Instantiate a SqlConnection using DbProviderFactory approach
DbProviderFactory factory =
DbProviderFactories.GetFactory(providerName);
connection = factory.CreateConnection();
connection.ConnectionString = connectionString;
CODE BLOCK 2 -Instantiate a SqlConnection using standard ADO.Net code
SqlConnection con = new SqlConnection(connectionString);
I had a look at some .net Framework assemblies and found the following
DbProviderFactories.GetFactory(providerName) will return an Factory object according to the given providerName.
Let's assume providerName indicates an SQL Provider so we will get an SqlClientFactory.
Afterwards factory.CreateConnection() will be called. In this case SqlClientFactory.CreateConnection() will be called which is implemented as
public override DbConnection CreateConnection()
{
return new SqlConnection();
}
I think the answer to your question is that calling the factory methods will call the methods of the provider specific classes and not the other way round!
To be sure what's going on, consider removing code block 2 - it isn't needed and adds complexity. Just use the factories capabilities to use the connection. For example, you have:
DbProviderFactory factory =
DbProviderFactories.GetFactory(providerName);
connection = factory.CreateConnection();
connection.ConnectionString = connectionString;
Add the following :
try
{
connection.Open();
var command = connection.CreateCommand();
command.CommandText = "SELECT * FROM mytable";
(..etc...)
We had to connect to MS SQL or Oracle, depending on user preference and this worked perfectly for us, the only thing unique will be the provider, connection string, and command text. Microsoft shows an example how to pull the providers from machine.config here.
Hope this helps, and if I'm incorrect, please let me know!

Managing SQL Server Connections

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.

Categories

Resources