I want to simply notify the user that they have successfully inserted new data to a database.
This is what I have so far:
try { cont.NewMember(txtSS.Text, txtName.Text, txtCity.Text, txtStreet.Text, txtZipcode.Text, txtEmail.Text, txtPhone.Text); }
catch (SqlException ex) { MessageBox.Show("The social security number \"" + txtSS.Text + "\"is already registered"); }
MessageBox.Show("Added succesfully");
I want to show the "Added successfully" only if (obviously) there wasn't an Exception. The update itself is working fine but the message "Added..." is always showing (even when there was an exception).
How can I solve this, using C#?
put the MessageBox... statement at the end of the try block
try
{
cont.NewMember(txtSS.Text, txtName.Text, txtCity.Text, txtStreet.Text, txtZipcode.Text, txtEmail.Text, txtPhone.Text);
MessageBox.Show("Added succesfully");
}
catch (SqlException ex)
{
MessageBox.Show("The social security number \"" + txtSS.Text + "\"is already registered");
}
this is not the correct approach. how would you know that the exception is because the SSN already existed in the database. It could throw an exception for many other cases like connection failure etc...
the best practice is to handle all these in the database.
Refer to handling exceptions in the database.
Related
I am new to C# and I'm struggling with very basic stuff... for instance I am now trying to compare an exception that I KNOW will print exactly the phrase "ORA-28007: the password cannot be reused" if I use Response.Write(ex.Message). However, in the block below, the comparison between ex.Message and the string just provided fails and it returns that Unhandled Exception I've put in the else clause... How should I be comparing the exception with the string?
catch (Exception ex)
{
if (ex.Message == "ORA-28007: the password cannot be reused")
{
Response.Write(ex.Message);
// TODO : Correct the exception to be presented in the popup instead of the same page.
// display = "The password cannot be reused! Pick a new one.";
// ClientScript.RegisterStartupScript(this.GetType(),
// "Error.", "alert('" + display + "');", true);
}
else
{
Response.Write("Unhandled exception: " + ex.Message);
}
}
If you're using the Oracle Data Provider for .NET you can catch OracleExceptions instead of Exceptions and get some more details by looking at the Errors property, which gives a list of OracleError objects:
catch(OracleException oex)
{
foreach (OracleError error in oex.Errors)
{
Console.WriteLine("Error Message: " + error.Message);
Console.WriteLine("Error Source: " + error.Source);
if(error.Number == 28007)
{
// do specific stuff
}
}
}
The title is a tad confusing, so hopefully I can explain it a tad better here. I want to change the title of the MessageBox that pops up on the screen if there is an error, since the default message is extremely long winded and I'd prefer to give a better explanation for the error that the user could understand.
private void Load_Click(object sender, RoutedEventArgs e)
{
if (comboBox.SelectedItem.ToString() == "Department Staff")
{
try
{
DataTable dt = dataSource.DataTableQuery("SELECT * FROM DepartmentStaff");
dataGrid.ItemsSource = dt.DefaultView;
}
catch (NullReferenceException ex)
{
MessageBox.Show("Unable To Connect To Database, Please Try Again Later.", ex.ToString());
}
}
else
{
try
{
DataTable dt = dataSource.DataTableQuery("SELECT * FROM Department");
dataGrid.ItemsSource = dt.DefaultView;
}
catch (NullReferenceException ex)
{
MessageBox.Show("Unable To Connect To Database, Please Try Again Later.", ex.ToString());
}
}
Take a look more carefully on the Message.Show() arguments:
Message.Show(text, caption); //the first one is text, the second one is caption.
The second argument is the caption (or title) while the first one is the message. Now in your use, you put up your exception message (which typically is very long) as the caption and that's why you get an "extremely long winded" caption (not message).
MessageBox.Show("Unable To Connect To Database, Please Try Again Later.", ex.ToString());
Don't do that! Instead, do it like this:
MessageBox.Show("Unable To Connect To Database, Please Try Again Later. " + ex.ToString(), "Error");
Simply put "Error" as caption argument.
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!
Hello I would like to write my userdefined exception to a log file.
So Instead of throwing my exception I would like to log that message into a txt file.
The constructor for my exception looks like this:
public OpenFileException(string pathToOpen, Exception innerexception)
: base("Couldn't find the path: " + pathToOpen, innerexception)
{
this.pathToOpen = pathToOpen;
}
This is how I am logging my exception at the moment:
try
{
string data = Read(txtLocation.Text);
txtInfo.Text = data;
}
catch (Exception ex)
{
WriteLog("[" + DateTime.Now + "]" + " " + ex.Message);
MessageBox.Show(" ");
throw new OpenFileException(txtLocation.Text, ex);
}
So what I'm asking is. How can I log my string "Couldn't find the path: " to a txt file?
I would normally catch and log the user defined exception outside the normal try/catch
try {
try {
string data = Read(txtLocation.Text);
txtInfo.Text = data;
} catch (Exception ex) {
throw new OpenFileException(txtLocation.Text, ex);
}
....
} catch(OpenFileException ex) {
WriteLog("[" + DateTime.Now + "]" + " " + ex.Message);
MessageBox.Show(" ");
} catch(Exception ex) {
WriteLog("[" + DateTime.Now + "]" + " " + ex.Message);
MessageBox.Show(" ");
}
You are creating a user defined exception so you can handle it differently
It looks a bit overkilling, why don't you use Log4Net and let it write files or send you emails depending on its configuration in the app.config?
basically you get all what you can want out of the box with no effort, then you can concentrate on what matters the most.
even if you decide to keep your current logic, I would anyway create a Logger class which does everything instead of having to specify DateTime.Now and other magic in every single catch block of your application.
You can use, instead of reinvent the wheel, log4net http://logging.apache.org/log4net/ or NLog http://nlog-project.org/wiki/Documentation both worth the effort to learn and use even in simple applications.
You need to find a way to get your exception thrown when a file is not found.
I don't think this is a good idea, because .NET already throws the FileNotFoundException when a file is not found. You should catch that and log the message that way.
try
{
string data = Read(txtLocation.Text);
txtInfo.Text = data;
}
catch (FileNotFoundException ex)
{
string log = String.Format("[{0}] Couldn't find the path: {1}"
, DateTime.Now
, ex.FileName);
WriteLog(log);
}
Don't make a new exception type when one already exists.
(Forgive the idiosyncrasies in my formatting)
From Framework Desing Guidelines:
Do override ToString when your exception provides extra properties.
Then you can just call log.Error(exception) and it will be logged just the way you wrote ToString() without extra actions.
Seriously, how can you handle all those exceptions without going nuts? Have I read one too many articles on exception handling or what? I tried refactoring this a couple of times and each time I seem to end up with something even worse. Maybe I should admit exceptions do happen and simply enjoy coding just the happy path? ;) So what's wrong with this code (besides the fact that I was lazy enough just to throw Exception instead of something more specific)? And by all means, don't go easy on me.
public void Export(Database dstDb)
{
try
{
using (DbConnection connection = dstDb.CreateConnection())
{
connection.Open();
DbTransaction transaction = connection.BeginTransaction();
try
{
// Export all data here (insert into dstDb)
transaction.Commit();
}
catch (SqlException sqlex)
{
ExceptionHelper.LogException(sqlex);
try
{
transaction.Rollback();
}
catch (Exception rollbackEx)
{
logger.Error("An exception of type " + rollbackEx.GetType() +
" was encountered while attempting to roll back the transaction.");
}
throw new Exception("Error exporting message " + Type + " #" + Id + ": [" + sqlex.GetType() + "] " + sqlex.Message, sqlex);
}
catch (Exception ex)
{
try
{
transaction.Rollback();
}
catch (Exception rollbackEx)
{
logger.Error("An exception of type " + rollbackEx.GetType() +
" was encountered while attempting to roll back the transaction.");
}
throw new Exception("Error exporting message " + Type + " #" + Id + ": [" + ex.GetType() + "] " + ex.Message, ex);
}
}
try
{
Status = MessageStatus.FINISHED;
srcDb.UpdateDataSet(drHeader.Table.DataSet, HEADERS,
CreateHeaderInsertCommand(), CreateHeaderUpdateCommand(), null);
}
catch (Exception statusEx)
{
logger.ErrorException("Failed to change message status to FINISHED: " +
Type + " #" + Id + ": " + statusEx.Message, statusEx);
}
}
catch (Exception importEx)
{
try
{
Status = MessageStatus.ERROR;
srcDb.UpdateDataSet(drHeader.Table.DataSet, HEADERS,
CreateHeaderInsertCommand(), CreateHeaderUpdateCommand(), null);
}
catch (Exception statusEx)
{
logger.ErrorException("Failed to change message status to ERROR: " +
Type + " #" + Id + ": " + statusEx.Message, statusEx);
}
AddErrorDescription(importEx.Message);
throw new Exception("Couldn't export message " + Type + " #" + Id + ", exception: " + importEx.Message, importEx);
}
}
Btw. So many times I tried really hard to be as specific as possible when forming questions - the result was no visits, no answers and no idea how to solve the problem. This time I thought about all the times when someone else's question caught my attention, guess this was the right thing to do :)
Update:
I've tried putting some of the tips into practice and here's what I came up with so far. I decided to change the behavior slightly: when it's not possible to set message status to FINISHED after successful export I consider it as job not fully done and I rollback and throw an exception. If you guys still have some patience left, please let me know if it's any better. Or throw some more criticism at me. Btw. Thanks for all the answers, I analyze every single one of them.
Throwing an instance of System.Exception didn't feel right, so I got rid of that, as suggested, and instead decided to introduce a custom exception. This, by the way, also doesn't seem right - overkill? This appears to be fine with public methods but a bit over-engineered for a private member, yet still I want to know there was a problem with changing message status instead of a problem with database connection or something.
I can see couple of ways of extracting methods here, but all of them seem to mix responsibilities which jgauffin mentioned in his comment: managing database connection, handling database operations, business logic (export data). Say the ChangeStatus method - it's some level of abstraction - you change the status of a message and you're not interested in how this thing happens, how the message is persisted, etc. Maybe I should use a Data Mapper pattern to further separate responsibilities, but in this still quite simple scenario I thought I'd get away with Active Record. Maybe the whole design is so convoluted right now, that I don't see where to make the cuts?
public void Export(Database dstDb)
{
try
{
using (DbConnection connection = dstDb.CreateConnection())
{
connection.Open();
using (DbTransaction transaction = connection.BeginTransaction())
{
// Export all data here (insert into dstDb)
ChangeStatus(MessageStatus.FINISHED);
transaction.Commit();
}
}
}
catch (Exception exportEx)
{
try
{
ChangeStatus(MessageStatus.ERROR);
AddErrorDescription(exportEx.Message);
}
catch (Exception statusEx)
{
throw new MessageException("Couldn't export message and set its status to ERROR: " +
exportExt.Message + "; " + statusEx.Message, Type, Id, statusEx);
}
throw new MessageException("Couldn't export message, exception: " + exportEx.Message, Type, Id, exportEx);
}
}
private void ChangeStatus(MessageStatus status)
{
try
{
Status = status;
srcDb.UpdateDataSet(drHeader.Table.DataSet, HEADERS,
CreateHeaderInsertCommand(), CreateHeaderUpdateCommand(), null);
}
catch (Exception statusEx)
{
throw new MessageException("Failed to change message status to " + status + ":" + statusEx.Message, statusEx);
}
}
Datasets are the root of all evil ;) Try using a ORM instead.
Read about single responsibility principle. your code does a lot of different things.
Do not catch exceptions only to rethrow them
Use using statement on transaction and connection.
No need to catch all different exceptions when all exception handlers do the same thing. The exception details (Exception type and Message property) will provide info.
Additionally to the great answer of jgauffin.
6 . don't catch exceptions just to log them. catch them on the top most level and log all the exceptions there.
Edit:
Because exception logging all over the place has at least these disadvantages:
The same exception may be logged several times, which fills the log unnecessarily. It's hard to tell how many errors actually occurred.
If the exception is caught and handled or ignored by the caller, there are still error messages in the log file, which is at least confusing.
Exception handling is a well discussed and is implemented in a well varied number of ways. There are some rules I try to abide by when handling exceptions:
Never throw System.Exception, generally there are enough types of exceptions to fill your requirement, if not, specialise. See: http://www.fidelitydesign.net/?p=45
Only ever throw an exception if the method itself cannot do anything but throw an exception. If a method can recover/handle expected variations of input/behaviour, then don't throw an exception. Throwing exceptions is a resource-intensive process.
Never catch an exception just to rethrow it. Catch and re-throw if you need to perform some additional work, such as reporting the exception, or wrapping the exception in another exception (typically I do this for WCF work, or transactional work).
These are just the things I do personally, a lot of developers prefer doing it ways in which they are comfortable....
Create a log class that handles fall backs for its own failures (i.e. tries SQL, if that fails writes to event log, if that fails, writes to a local log file, etc).
Also I don't recommend you catch an error and throw a different one. Every time you do so you are losing valuable trace/debug information about the original exception source.
public void Export(Database dstDb)
{
try
{
using (DbConnection connection = dstDb.CreateConnection())
{
connection.Open();
using (DbTransaction transaction = connection.BeginTransaction())
{
// Export all data here (insert into dstDb)
ChangeStatus(MessageStatus.FINISHED);
transaction.Commit();
}
}
}
catch (Exception exportEx)
{
LogError(exportEx);// create a log class for cross-cutting concerns
ChangeStatus(MessageStatus.ERROR);
AddErrorDescription(exportEx.Message);
throw; // throw preserves original call stack for debugging/logging
}
}
private void ChangeStatus(MessageStatus status)
{
try
{
Status = status;
srcDb.UpdateDataSet(drHeader.Table.DataSet, HEADERS,
CreateHeaderInsertCommand(), CreateHeaderUpdateCommand(), null);
}
catch (Exception statusEx)
{
Log.Error(statusEx);
throw;
}
}
Also for any situation where you feel there are additional try/catch blocks needed, make them their own method if they are too ugly. I like Stefan Steinegger's answer, where the top level call in your app is the best place to catch.
Part of the problem here I imagine is that something is mutable that causes you to try to set the status after a failure. If you can factor your object to being in a consistent state whether or not your transaction works you don't have to worry about that part.