I am trying to write a method that will check if a database connection is valid or not. Here is the code behind my Test Connection button.
private void TestConn_btn_Click(object sender, EventArgs e)
{
DbConnection DBConnTest;
if (DataSrc_cbx.SelectedIndex == 1)
{
DBConnTest = new SqlConnection("Server="+DatabaseAddress_Value+"; Database="+DatabaseName_Value+";Trusted_Connection=true");
try
{
DBConnTest.Open();
MessageBox.Show("\nTEST SUCCESSFUL\n");
}
catch (Exception exception)
{
MessageBox.Show("TEST FAILED Exception Thrown: " + exception.Message);
}
finally
{
DBConnTest.Close();
}
}
}
The problem is that there is no exception thrown when I enter an invalid Database address ( or leave it empty all together), same applies to the Database name. It only throws an exception when there is no connection string, or in an incorrect format. So my question is, How do I make it check if there is indeed a server and a database on that server with the names input?
You can apply validations on your Web Page if the fields are empty then prompt user to enter something. Now use this statement to check whether this database exist or not??
select name from sys.sysdatabases
where dbid=db_id()
for user you need to ..
SELECT id FROM user WHERE login="JohnSmith"
and see if it gives you any rows. If yes - user exists.
You can use this work-around.
You need to execute a query to connect to the database.
For SQL Server, I usually use IDbCommand.ExecuteScalar to execute:
SELECT ##VERSION
For Oracle:
SELECT banner from v$version where banner like 'Oracle%'
Would you provide the complete code, please?
It would be something like:
try
{
using(SqlConnection conn = ...)
{
conn.Open();
using(SqlCommand command = conn.CreateCommand())
{
command.CommandText = "SELECT ##VERSION";
var result = (string) command.ExecuteScalar();
MessageBox.Show("\nTEST SUCCESSFUL\n" + result);
}
}
}
catch(Exception ex)
{
MessageBox.Show("TEST FAILED Exception Thrown: " + exception.Message);
}
Your code is working for me. The issue here is that you have to wait till the SQL timeout period elapses before the exception is thrown. This will not be a method that returns an immediate answer. If you wrap this try/catch with a WaitCursor, you will at least see when the code is running.
private void TestConn_btn_Click(object sender, EventArgs e)
{
this.Cursor = Cursors.WaitCursor;
DbConnection DBConnTest;
if (DataSrc_cbx.SelectedIndex == 1)
{
DBConnTest = new SqlConnection("Server="+DatabaseAddress_Value+"; Database="+DatabaseName_Value+";Trusted_Connection=true");
try
{
DBConnTest.Open();
MessageBox.Show("\nTEST SUCCESSFUL\n");
}
catch (Exception exception)
{
MessageBox.Show("TEST FAILED Exception Thrown: " + exception.Message);
}
finally
{
DBConnTest.Close();
}
}
this.Cursor = Cursors.Default;
}
Perhaps try:
using (SqlConnection conn = new SqlConnection(builder.ToString()))
{
try
{
conn.Open();
}
catch (SqlException ex)
{
foreach (SqlError error in ex.Errors)
{
Console.WriteLine(error.Number);
}
}
catch (Exception ex)
{
}
}
It will return the DB error code (run the following query for a list of error codes:
select * from sys.messages where language_id=1033 and severity between 11 and 16
Microsoft also provide some guidance here:
http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlerror.number(v=vs.110).aspx
Your code looks incomplete!
Take this example from Microsoft.conexão c# com sql server 2008
Good luck!
Related
I have a piece of code that iterates through a list of SQL commands that should be processed all as part of one transaction. I want to have a way of knowing if that transaction was successful for error logging and handling purposes. At this moment in time for some reason I have a problem seeing any kind of actual exception or unsuccessful commit. I am using the code below right now. The try catch is from the MSDN page recommendation. Please feel free to poke any other holes in this that you can see that are not 100% about my question. These are all commands of SqlCommands of the stored proc type with parameters added to it prior to adding it to the list of SQL commands.
public static async Task UpdateSQL(string inputQuery,
string inputId, List<SqlCommand> commandList, TraceWriter log)
{
try
{
string str = ConfigurationManager.ConnectionStrings
["connString"].ConnectionString;
log.Info($"Running query: {inputQuery}");
int commandRows = 0;
using (SqlConnection conn = new SqlConnection(str))
{
conn.Open();
SqlTransaction tr = conn.BeginTransaction();
try
{
SqlCommand cmd = new SqlCommand(inputQuery, conn);
cmd.Transaction = tr;
foreach (var command in commandList)
{
command.Connection = conn;
command.Transaction = tr;
log.Info($"{command.CommandText} query running"); //last log output if unsuccesful (based on end result in database)
commandRows += await command.ExecuteNonQueryAsync();
}
log.Info($"total rows updated: {commandRows}");
tr.Commit();
conn.Close();
}
catch(Exception ex)
{
Console.WriteLine($"Commit Exception Type: {ex.GetType()}");
Console.WriteLine($" Message: {ex.Message}");
try
{
tr.Rollback();
conn.Close();
log.Info($"{inputId} transaction rolled back");
}
catch (Exception ex2)
{
// rollback fail Exception
log.Info($"Rollback Exception Type: {ex2.GetType()}");
log.Info($" Message: {ex2.Message}");
conn.Close();
}
}
}
}
Try and catch SqlException
Then do this:
StringBuilder sqlErrorMessages = new StringBuilder("Sql Exception:\n");
foreach (SqlError error in ex.Errors)
{
sqlErrorMessages.AppendFormat("Mesage: {0}\n", error.Message)
.AppendFormat("Severity level: {0}\n", error.Class)
.AppendFormat("State: {0}\n", error.State)
.AppendFormat("Number: {0}\n", error.Number)
.AppendFormat("Procedure: {0}\n", error.Procedure)
.AppendFormat("Source: {0}\n", error.Source)
.AppendFormat("LineNumber: {0}\n", error.LineNumber)
.AppendFormat("Server: {0}\n", error.Server)
.AppendLine(new string('-',error.Message.Length+7));
}
You'll only get an exception in C# if your error's severity is 16 or above. If you are using a PRINT, you won't get an exception in .NET.
If you can edit the raise error code, this would cause a SqlException in C#:
RAISERROR('Some error message', 16, 1)
You can then get to each individual error in the SqlException.Errors collection.
Just a side-note - SQL Server will continue to run commands after the RAISERROR if you don't RETURN directly afterwards. If you don't return, you can get multiple errors back.
I have a function that reads values from specified columns. It looks like this:
private bool OpenConnection() // Just opens the connection. No error here.
{
try
{
conn.Open();
return true;
}
catch (MySqlException ex)
{
MessageBox.Show("Connection not opened");
return false;
}
}
private void getStats(string user, string cate, string score)
{
if (OpenConnection())
{
try
{
string getuserstats = $"SELECT {cate} FROM scores WHERE user = '{user}'";
MySqlCommand cmd = new MySqlCommand(getuserstats, conn);
MySqlDataReader getscore = cmd.ExecuteReader();
MessageBox.Show(getscore.Read().ToString()); //outputs false.
while(getscore.Read())//does not run
{
MessageBox.Show("Reading!");//does not run
score = getscore.GetString(0);//does not run
MessageBox.Show(score); //does not run
}
getscore.Close();
conn.Close();
}
catch (Exception ex)
{
MessageBox.Show("Error getting scores!");
conn.Close();
}
}
else
{
MessageBox.Show("Connection not opened!");
}
}
The SQL command part seems to run fine, I tested it with some different querys and they all worked fine.
However, the SQL reader itself doesn't seem to run. I do not get an exception error either.
I used a message box to show the boolean value of my reader reading, and it outputted false. Why is this?
The most likely reason that Read() returns false is that no records match the query that you're performing. Are you sure there are any records in that table matching the given user name? And that the database you are connecting to is the one you think it's connecting to.
This won't be related, but the MySqlCommand and MySqlDataReader are both disposable, as is the connection, so you should place them in "using" blocks, or explicitly dispose them.
I am working on a MVC web page that edits a SQL DB table. In my controller, I have a DB call to increment an entity table. Then if successful, creates a new row in my target table (not the entity table).
The problem I am running into is I keep getting the following error:
The ConnectionString property has not been initialized.
However this only happens after the entity table has been incremented. Not sure where to go on this, so I am hoping that by posting some code, someone would be able to help me find my error.
so here is the obligatory code:
My SQL Connection:
private SqlConnection con;
public BaseRepository()
{
con = new SqlConnection(ConfigurationManager.ConnectionStrings["SqlServerConnection"].ToString());
}
My Entity Table Increment Call:
public int GetNextId()
{
try
{
using (con)
{
DynamicParameters dynParam= new DynamicParameters();
dynParam.Add("#entity_name", "insert_object ");
con.Open();
var value = con.Execute(SP_GET_NEW_ID, dynParam, commandType: CommandType.StoredProcedure);
con.Close();
return value;
}
}
catch (Exception ex) { throw ex; }
}
Finally, here is the Row Insert Code:
public int InsertRowCode(InsertObject ccModel, UserModel appUser)
{
var value = GetNextId();
if (value == 1)
{
try
{
using (con)
//this is where the code breaks and jumps the the exception ex in my catch
{
con.Open();
var dP = new DynamicParameters();
//(add 14 dynamic Parameters here)
var result = con.Execute(SP_SAVE_CORRECTION_CODES, dP, commandType: CommandType.StoredProcedure);
con.Close();
return result;
}
}
catch (Exception ex)
{
throw ex;
}
}
else { throw new Exception("Busted"); }
}
Any help is greatly appreciated. TIA
Don't use shared connection objects.
When you exit this block:
using (con)
{
//...
}
That connection object is now disposed and can't be used anymore. Don't worry about trying to optimize your connections, the connection pool does a very good job of that already. Create your connection objects where you need them, use them, and dispose them in a tight scope:
using (var con = new SqlConnection(connectionString))
{
//...
}
As a side note, this is superfluous:
catch (Exception ex)
{
throw ex;
}
That catch block isn't doing anything for you, and is actually deleting important information about the exception. Just remove that try/catch entirely.
If, on the other hand, you ever do want to do something with an exception before re-throwing it, just use the keyword throw by itself:
catch (Exception ex)
{
// log something, etc.
throw;
}
This would allow the exception to continue up the stack unmodified, preserving the actual error information.
I have an exception occurred when the Database connection failed in a Class. The problem is how do I notify my Main Window that this exception is caught and show a message box to notify my user?
Thanks
Use the Try ... Catch clause like this:
try
{
// The code that could generate an exception
}
catch(Exception ex)
{
MessageBox.Show("Error: " ex.Message);
}
Or if you're using SQL-Server connection, use it like this:
try
{
// The code that could generate an exception
}
catch(SqlException ex)
{
MessageBox.Show("SQL Error: " ex.Message);
}
Thanks. I may have not make my question clearly. I mean this exception
is occurred in one class, but the message box should be show in an
other windows class. So how do I communicate and show this error?
From your clarification in one of the comments:
So if you have class TestClass.cs with method Test in it.
public void Test()
{
//if you want to throw an exception defined by your business logic
if(someCondition == false)
throw CustomException();
//if you have exception in the code
int a = 5;
int b =0;
//here you will be thrown an exception can't divide by 0.
int c = a/b;
}
Your winform Button Click or whatever
public void Button_Click1(object sender, EventArgs e)
{
try
{
TestClass cl = new TestClass();
cl.Test();
}
catch(CustomException custEx)
{
//this for your Bussines logic exception
//write your message
}
catch(DivideByZeroException div)
{
//this for divide by zero exception
//write message
}
//you can catch all other exception like this but I don't advice you to do that
catch(Exception ex)
{
//for this to working properly, this catch should be under all of others(last priority)
}
}
In c#, can I catch all errors about (non) connectivity to an Oracle database?
I don't want to catch error about badly written query but only errors like No listener, connection lost...
If queries are badly written (or table are missing) then this is my fault.
But if Oracle or the network is down then this should be held by another department.
Write your code in which you build the connection in a try catch part:
try
{
BuildConnection(connectionString);
}
catch (OracleException ex)
{
//Connectivity Error
}
Errors between ORA-12150 to ORA-12236 are related to connection errors. A few examples:
ORA-12154: TNS:could not resolve the connect identifier specified
ORA-12152: TNS:unable to send break message
ORA-12157: TNS:internal network communication error
Please refer to https://docs.oracle.com/cd/E11882_01/server.112/e17766/net12150.htm
Simple answer for this Type of problem is Use Try Catch Block like
try
{
// your code
}
catch (OracleException ex)
{
}
MSDN HELP
Sure - you can catch specific exception types, or if they're all the same exception type, you can catch it, check to see if it's a specific type, and re-throw ones you don't want to handle. Not having your syntax, here's an example...
try
{
// your Oracle code
}
catch (OracleException ex)
{
if (ex.Message == "Something you don't want caught")
{
throw;
}
else
{
// handle
}
}
errors like No listener, connection lost are still caught in System.Data.SqlClient.SqlException, however, you may inspect ErrorCode and Errors to handle different situations accordingly, say, not listener or connection lost etc.
MSDN does not seem to document all possible errors, however, you may write a few unit tests or integration tests to learn what appear in ErrorCode and Errors, then write error handlers in production codes accordingly.
OracleException contains only ErrorCode not Errors. So you may be using switch(e.ErrorCode) to handle different situations.
I observed that each time a network exception occurs, then a SocketException can be found in inner exceptions.
I also observed that when a network exception occurs, the first inner exception is of type «OracleInternal.Network.NetworkException» but unfortunately, this class is internal...
Based on this observations, I would code something like this:
public void RunQuery()
{
try
{
var con = new OracleConnection("some connection string");
con.Open();
var cmd = con.CreateCommand();
// ...
cmd.ExecuteNonQuery();
}
catch (Exception ex) when (IsNetworkException(ex))
{
// Here, a network exception occurred
}
catch (Exception ex)
{
// Here, an other exception occurred
}
}
private static bool IsNetworkException(Exception ex)
{
var exTmp = ex;
while (exTmp != null)
{
if (exTmp is SocketException)
return true;
exTmp = exTmp.InnerException;
}
return false;
}