How to get user defined SQLException number with Dapper - c#

My stored procedure is throwing custom errors to handle validation within a multi user web app. This is working as expected in SQL Server with error number 50001 being returned however when my C# code catches the error it always has the error number 50000 instead of 50001 therefore I cannot treat the errors differently.
How can I catch error number 50001? Note that I am using Dapper to execute all stored procedures.
SQL
THROW 50001, 'Client already has an Active Visit! THIS IS DEV!!!!',1;
Msg 50001, Level 16, State 1, Line 1
Client already has an Active Visit! THIS IS DEV!!!!
C#
catch (SqlException ex)
{
var errorHandler = new ErrorHandler();
var msg = errorHandler.ErrorMessage(ex);
if (ex.Number == 50001)
{
return BadRequest(msg);
}
else
{
return StatusCode(500, msg);
}
}
catch (Exception ex)
{
var errorHandler = new ErrorHandler();
return StatusCode(500, errorHandler.ErrorMessage(ex));
}
EXAMPLE

SQL server error 50000 is reserved for general user defined message, so it sounds like it's not finding error 50001 in sys.messages. You can try to add the error using the stored procedure sp_addmessage.
Once that is done, you can call it like this:
RAISERROR(50001, 1, 1)
Another reason it could be error 50000 is if you are raising the SQL error in a SQL TRY/CATCH as that will always return a 50000 error code.
Just tried this code myself:
using (var cmd = new SqlCommand("THROW 50001,'error',1;", conn))
{
cmd.ExecuteNonQuery();
}
And that does return ex.Number 50001 so it must be a problem in your SQL. Like I said above, it could be caused by a TRY/CATCH as this won't save the original error code number.

Related

C# Retry Policy: How to check what exception you receive as a variable?

I have a retry policy created for SQL Exceptions but it seems to not be retrying properly.
I am currently trying to debug and I want to create a temporary code line to test if the exception is a SQL Exception:
if (exception == SQLException) then bool correct = true;
But how would I create an exception variable?
I am currently causing the exception by using RAISERROR('test', 16, 1); in the stored procedures in the database and also creating a SQL timeout.
Just want to check if the exception I'm receiving is a SQL Exception or if it's not even registering.
Thank you
Not sure enough about the context, but if you have the exception object, then try the is operator
if (ExceptionObject is SqlException )
{
//run the retry logic for SqlException
}
The details are here:
https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/operators/type-testing-and-cast
Just catch the SqlException and check for the Class and State properties:
if (exception is SqlException sqlException)
{
if(sqlException.Class == 16 && sqlException.State == 1)
{
}
}

Catch RAISERROR from SQL Server in .NET

I have a stored procedure in SQL Server that throws an error whenever a condition is hit. In order to catch this error and display it to the user, I use
try
{
//code
}
catch (Exception e)
{
return BadRequest(e.Message);
}
This catches most of the cases but on the other hand, this procedure has some print messages that also get caught by this Exception. Is there a way to catch the exception thrown only from RAISERROR and ignore this print message from SQL Server?
All info and error messages generated during command execution are buffered and available when a SqlException is caught. The Message property includes the text of all info messages (print statements and errors with a severity of less than 11) and the warnings/errors that caused the exception.
To ignore info messages, use the SqlException Errors collection and process only those with severity (SqlError.Class property) of 11 or higher:
catch (SqlException e)
{
var sb = new StringBuilder();
foreach(var error in e.Errors)
{
if(error.Class > 10) sb.AppendLine(error.message);
}
return BadRequest(sb.ToString());
}

TransactionScope.Complete() returns error

I am facing some strange error while executing following code.
I debugged all methods and found no error but scope.Complete(); line returns an error "Transaction has aborted" and InnerException is "The COMMIT TRANSACTION request has no corresponding BEGIN TRANSACTION."
InsertEntries(myObject) calls few more methods within for making entries to near about 12-15 different tables in SQL Server. It used StoredProcedues to do that.
I am using EntityFramework and SQLServer.
NOTE:
1 - Everything works fine without TransactionScope.
2 - Error returns on scope.Complete(); line. No other errors.
using (TransactionScope scope = new System.Transactions.TransactionScope()
{
try
{
myObject.IsMain = false;
InsertEntries(myObject);
myObject.IsDuplicateNumber = IsDuplicateNumber;
myObject.RecNum = RecNum;
myObject.NextNumber = nextNumber;
scope.Complete();
}
catch (Exception ex)
{
throw ex;
}
}

c# LinqToSql exception handling when database is offline

Building an C# MVC webapplication with Linq to Sql for querying the SQL database.
I am trying to catch an exception if the database should go offline to avoid the yellow screen of death.
After debugging, I found two things. First, the creation of the DataContext does not check if the sql server is available. Second, there is an Error message (Or an exception!?) stored in the rows variable.
The Catch statement in the code below is never reached. So I get the Yellow screen of death when trying to read data from the Model in the View.
Why isn't the Catch statement reached?
Code:
try
{
//Creating DB Context
var con = ConfigurationManager.ConnectionStrings["teststring"].ConnectionString;
TestDataContext db = new TestDataContext(con);
//Querying database. This should cause an exception to be thrown!?
var rows = from s in db.Table
orderby s.Id descending
select s;
//Returning the View with the data
return View(rows);
}
catch (Exception ex)
{
ErrorInfo err = new ErrorInfo("Something went wrong when trying to query the database. See the log for details.");
err.WriteToErrorLog(ex);
return View("Error", err);
}
have you tried to use SQLException
try
{
//Creating DB Context
var con = ConfigurationManager.ConnectionStrings["teststring"].ConnectionString;
TestDataContext db = new TestDataContext(con);
//Querying database. This should cause an exception to be thrown!?
var rows = from s in db.Table
orderby s.Id descending
select s;
//Returning the View with the data
return View(rows);
}
catch (SqlException ex)
{
ErrorInfo err = new ErrorInfo("Something went wrong when trying to query the database. See the log for details.");
err.WriteToErrorLog(ex);
return View("Error", err);
}
Firstly: as #ofir mentioned you should call .ToList() method in order to execute LINQ statement. so you should call it on your try block to be able to catch the exception.
Secondly:
you shouldn't show Yellow error screen to end users because of security reasons, you can enable CustomError in web.config file to show a default page when an exception is thrown and redirect it to an Error page
<customErrors mode="On" defaultRedirect="~/ErrorPages/GeneralError">
</customErrors>

C# oracle : catch all exceptions relative to connectivity?

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

Categories

Resources