I have a working ODBC connection on one of the projects, but I want to DRY and have the connection class available to the entire solution.
So, I removed the repeating code from every project and created the following class which I then referenced on all of the projects:
using System;
using System.Data.Odbc;
public class ConnectWithDb
{
public OdbcConnection Connection;
public OdbcConnection Connect()
{
try
{
string connectionString = "Driver={" + Constants.DriverODBC + "};Dbq=" + Constants.DbFileName + ";Uid=Admin;Pwd=;";
OdbcConnection Connection = new OdbcConnection(connectionString);
Connection.Open();
return Connection;
}
catch (Exception ex)
{
throw new Exception(ex.Message);
}
}
}
Then, on each project and before the Main() method, I do:
private ConnectWithDb dbConnection = new ConnectWithDb();
No errors there. The problem is that when I try to create a command inside any of the methods, I get an error like this:
OdbcCommand command = dbConnection.CreateCommand();
dbConnection is underlined and states An object reference is required for the non-static field, method or property 'Program.dbConnection'
I've tried setting some methods and values as static, but that gives a whole bunch of other errors.
I guess that ConnectWithDb is not returning an actual connection... is that right? What am I doing wrong here?
Thank you!
Related
This is baffling me. I have this line of code that is causing the problem
string prodID = DBTools.getProdID(args[0]).ExecuteScalar().ToString();
When I run this in my program I eventually get an error.
public static SqlCommand getProdID(string server)
{
string sql = "SELECT Password FROM UTrainID";
SqlCommand cmd = createCmd(server, "AACSMapping", sql);
cmd.Connection.Open(); // this generates the System.NullReferenceException
return cmd;
}
The thing that is baffling me about this is that I have a UnitTest that tests this that works perfectly.
[TestMethod]
public void getProdIDTest()
{
string ID = UTrain.DBTools.getProdID("PN1173312").ExecuteScalar().ToString();
Assert.IsTrue(ID.Equals("XXXXXXXXX"));
}
When I run this console application I've checked that the Args[] values are right i.e. it's the same value that I have in the UnitTest. The other things that is bothersome about this is that when I try to debug it by stepping through the code it works fine! That tells me that it's a timing problems of some type but that's beyond me. Here is the code that creates the actual connection.
public static SqlConnection createConnection(string server, string initcat)
{
try
{
SqlConnectionStringBuilder strBuild = new SqlConnectionStringBuilder();
strBuild.IntegratedSecurity = true;
strBuild.InitialCatalog = initcat;
strBuild.DataSource = server;
SqlConnection conn = new SqlConnection(strBuild.ConnectionString);
return conn;
} // end try
catch (Exception e)
{
writeErrorMessage(e, "Could not create connection.");
return null;
}
}
I don't know that it makes any difference but the reason I break the code up like this is I'm connecting to a number of different databases so it makes it easier to do it like this I feel.
Thanks for the comments. I finally found the problem. It was throwing a error that was being written to the error log file. It was a "Type initializer for SqlConnection threw an exception" When I searched for that error message most concerns were with the app.config file. I checked that and it was not formatted correctly. There was an extra >. I can see why the unit test might have worked when running unit tests I guess they wouldn't load the app.config file, but I still don't understand why stepping through with the debugger would work correctly?
I have a program in C# where I created various class, and all of them need to make calls to the database. So I decided to create a static class that handles all the calls to allow me to apply far-reaching changes very easily. Within that class I have functions that call the various parts of SqlCommand (ExecuteReader(), etc) I finally got tired of rewriting all the connection code, and abstracted it out to another function called getSqlCommand() which just returns an initialized SqlCommand which I use to perform the various commands. I've chosen to not pass the SqlCommand back to the other programs (though it is a public method in case I need it) because there is some pre-processing if you will that I may do before I had the results back to the program.
My question is, if/when the SqlConnection closes? Since it is being passed back as a return value in a SqlCommand, will it be left open? and if so, can I close it? Here is some code (slightly stripped down) so you can see what I am doing, thanks in advance!
The function to create the SqlCommand:
public static SqlCommand GetSqlCommand(string query)
{
using (SqlConnection dbConnection = new SqlConnection( SQLConn )) {
dbConnection.Open();
SqlCommand cmd = new SqlCommand( query, dbConnection );
cmd.CommandTimeout = 0;
return cmd;
}
}
An example of the usage of the command in the static class:
public static SqlDataReader executeReader( string query )
{
try {
return GetSqlCommand(query).ExecuteReader();
} catch (SqlException) {
//Notify User and Resolve Error
}
return null;
}
A SqlConnection is closed when you call Dispose. Exiting the using block does that. The connection will be closed.
That's all there is to it. It will not magically stay open because ADO.NET does not know and cannot find out that you returned the connection object.
Move the connection out of the GetSqlCommand method. Pass the connection object into that method. GetSqlCommand has no business in creating a connection. It should take a connection, use it, but not close it.
The connection closes before the code exits the GetSqlCommand method. That means that the command object that it returns is useless.
The using construct creates a try ... finally block, where it disposes the connection at the end of the block. As disposing the connection also closes it, the connection is already closed before the command object is returned from the method to the caller.
The using keyword is equivalent to use try finally, and within the finally block your connexion will be disposed
SqlConnection dbConnection = new SqlConnection( SQLConn );
try
{
dbConnection.Open();
SqlCommand cmd = new SqlCommand( query, dbConnection );
cmd.CommandTimeout = 0;
return cmd;
}
catch(Exception ex)
{
}
finally
{
dbConnection.Dispose();
}
And even if there is a return statement inside a try block , the block finally will always be executed
I'm just learning asp.net/C# and am building my first application.
In my application, I am rendering data from sql on almost every view.
My controllers are getting large, because every time I make a request, I'm using somthing like:
try
{
sqlConnection = new SqlConnection(dbConnectionString);
SqlCommand command = new SqlCommand("sp_Test", sqlConnection);
command.CommandType = CommandType.StoredProcedure;
sqlConnection.Open();
return command.ExecuteNonQuery();
sqlConnection.Close();
}
catch (SqlException ex)
{
Console.WriteLine("SQL Error" + ex.Message.ToString());
return 0;
}
Is there a way to turn the sql into a simple using block?
Maybe something like:
using(myConnection){
SqlCommand command = new SqlCommand("sp_Test", sqlConnection);
command.CommandType = CommandType.StoredProcedure;
}
There are many better approaches do it. You can create a SqlHelper class that can be used to execute stored procedures and SQL queries and also return DataReader and DataTable/DataSets.
public class SqlHelper
{
public SqlHelper(string connString)
{
}
public DataSet GetDatasetByCommand(string Command);
public SqlDataReader GetReaderBySQL(string strSQL);
public SqlDataReader GetReaderByCmd(string Command);
public SqlConnection GetSqlConnection();
public void CloseConnection();
}
You can see one such sample here:
http://www.nullskull.com/a/1295/sql-helper-class-in-c.aspx
If you want more advanced approach you can go for Enterprise Library Data Access Block
http://msdn.microsoft.com/en-us/magazine/cc163766.aspx
The best thing to do is refactor that statement into a seperate method. It looks like the only thing that could vary is the name of the procedure.
So create an object with two properties, a boolean success and an error message.
Call the function and pass in the name of the sql command. Your function should run your repeated code in the try block based on the given procedure name, then return an object with true/false and an error message if the call failed. This should make your controllers much smaller. Example code for the controller:
var result = MyNewMethod("sp_Test");
if(!result.Success)
{
Console.WriteLine(result.ErrorMessage);
return 0;
}
I have created a generic Database handler class for my app.
Im using a local database so SqlCeConnection class is being used here.
What I would like to do is test that the Connection string is valid, so update the connection status to the user before I execute connection.Open();
lets say
SqlCeConnection conn = new SqlCeConnection(connectionString);
//so far we have only created the connection, but not tried to open it
//Would be nice to update the UI to say that conn is OK
conn.testConnection();
conn.Open();
I was thinking of writing a method that attempts to open then close the connection, am I right in thinking this or is there a better way.
testing for connectivity adds extra overhead. why not directly open connection and put the code inside Try-Catch
try
{
conn.Open();
}
catch(SqlCeException ex)
{
// output the error to see what's going on
MessageBox.Show(ex.Message);
}
You can use DbConnectionStringBuilder with property ConnectionString, it will throw exception if connection string is not correct format:
public static class Extension
{
public static void TestConnection(this DbConnection connection)
{
var builder = new DbConnectionStringBuilder
{
ConnectionString = connection.ConnectionString
};
}
}
With this way you don't need to really open connection to database.
I have created a class to ease the use of SQL server within my app.
public static class SqlServer
{
public static void QueryNoReturn(string ConnectionString, string Query, SqlParameter[] Parameters, bool IsStoredProcedure)
{
using (SqlConnection conn = new SqlConnection(ConnectionString))
{
// Create the command to run
SqlCommand command = new SqlCommand(Query, conn);
// If we are running a stored procedure
if (IsStoredProcedure)
command.CommandType = System.Data.CommandType.StoredProcedure;
// Add parameters if they exist
if (Parameters != null)
command.Parameters.AddRange(Parameters);
try
{
// Open the connection to the database
conn.Open();
// Execute the command and assign to the result object
command.ExecuteNonQuery();
conn.Close();
command.Parameters.Clear();
}
catch (SqlException sqlex)
{
throw new Exception(
string.Format("{0} \"{1}\"", IsStoredProcedure ? "Procedure" : "Query", Query),
sqlex);
}
}
}
}
If I am calling this static method many times a second (approx. 50) then will I see issues with thread safety?
I could easily create a Factory or some other instance specific object, but I went with this option out of simplicity.
Since you are not using any shared resources of the class, this appears to be "thread-safe".
This of course disregards any concurrency issues on the database itself.
You should wrap the SqlCommand creation in a using statements as well.
Since you are creating the SqlConnection in a using statement, you don't need to explicitly call Close on it, as it will be done when the connection is disposed.
No. You could get into thread safety problems when you access shared resources, but you don't do that (at least not in this method).
By the way, move the conn.Close(); to a finally clause, that way the connection is closed, even when you get an exception.