Make the error shorter - c#

I made a program in c#(I don't put here the code because there are lot of classes),and I made Exceptions to throw the mistakes,and when a mistake occurs this is what appears in the console:
System.Exception: Student whit id:1 already exists! at
StudentManagment.Service.AbstractService`4.Add(E entity) in
C:\Users\Robbi\source\repos\StudentManagment\StudentManagment\Service\AbstractService.cs:line
34 at StudentManagment.Domain.Program.Main(String[] args) in
C:\Users\Robbi\source\repos\StudentManagment\StudentManagment\Program.cs:line
23
And my question is, How can I make that in the console to appear just
Student whit id:1 already exists!

Catch the exception into a variable and output the exception.Message only. You are seeing a stack trace - ie all the methods that are in execution at the point of error. StackTraces are useful for debugging purposes, but not so great for displaying information to a user.
i.e
try
{
//do error here
}
catch(Exception e)
{
Console.WriteLine(e.Message);
}

This is a very beginner issue
While you show no code, heres some semi fake code to answer the question
try
{
do_it();
}
catch (Exception myEx) // you can do different things with different exception types
{
Console.WriteLine("Error: "+myEx.Message);
}

You have to use
ex.Message
where ex is your exceptption, something like
try
{
...
}
catch (Exception ex)
{
Console.Write(ex.Message);
}
Of course, edit this minimal snippet code to satisfy your needs

Related

How should I handle unapproriate situations in C#

I'm a beginner and haven't had a job yet, so I never work experience with code.
My question is:
How should I handle situations, when user enters a value, that doesn't throw exception, but is unacceptable and and program should be closed.
Should I throw an exception with some message in catch block, or it would be enough to just show a message ?
Its really up to the requirements of the application that you are developing. But c# has a specific exception type for this:
InvalidArgumentException
And you can use it like this:
if (!ValidateUserInput(input))
throw new InvalidArgumentException ("input is invalid");
You can then catch that further up in the application and decide how to handle it
It all depends of You. Depends on what You want to achieve.
There is no ultimate answer to this.
It is good to do everything You said. Throw exeption in try catch block and then give a information for user and close program.
Additionally log the error with more informataion to a file or databases.
Message box is good, because is user firendly.
Throw exeption is also good because is very readable for developer - when they read You code they see this is a bad sitiation.
For example what to do:
try
{
if (IsErrorValidation())
{
throw new Exeption("You input wrong data");
}
}
catch (Exception e)
{
MessageBox.Show("Error" + e.Message );
CloseProgram();
}
You create new Exception with Your massage.
Better is create Your own type of Exeption for example ErrorValidationException or use the predefined InvalidArgumentException which exist in C#
try
{
if (IsErrorValidation())
{
throw new ErrorValidationException("You input wrong data");
}
}
catch (ErrorValidationException e)
{
MessageBox.Show("Error" + e.Message);
CloseProgram();
}
catch (Exeption e)
{
...
}
Then You can use this type of exception later and You can serve this type of exception in a different way

Catch DB error details

I want a better way to catch database error details.
I'm currently using :
try
{
dbconn.table.AddObject(newRow);
dbconn.SaveChanges();
}
catch (Exception ex)
{
Console.WriteLine("DB fail ID:" + Row.id);
}
many times I found the Exception ex can no give me details on how the exception happen.
I think these exception most likely to be the DB connection kind.
So is there a better way to catch this ?
You should also output the exception. Most of the time, it holds useful and detailed information (e.g. names of violated constraints). Try this:
try
{
dbconn.table.AddObject(newRow);
dbconn.SaveChanges();
}
catch (Exception ex)
{
Console.WriteLine("DB fail ID:" + Row.id);
Console.WriteLine(ex.ToString());
}
For full details, use the ToString() method, it will give you the stack trace as well, not only the error message.
Use Console.WriteLine(ex.GetType().FullName) (or put a breakpoint and run under a debugger) to see the actual exception type being thrown. Then visit MSDN to see its description and base classes. You need to decide which of the base classes provides you with the information needed by exposing such properties. Then use that class in your catch() expression.
For Entity Framework, you might end up with using EntityException and then checking the InnerException property for the SQL exception object that it wraps.
try
{
dbconn.table.AddObject(newRow);
dbconn.SaveChanges();
}
catch (EntityException ex)
{
Console.WriteLine("DB fail ID:" + Row.id + "; Error: " + ex.Message);
var sqlExc = ex.InnerException as SqlException;
if (sqlExc != null)
Console.WriteLine("SQL error code: " + sqlExc.Number);
}
Instead of Exception use SqlException.
SqlException give you more detail. it has a Number property that indicate type of error and you can use that Number in a switch case to give some related information to user.
In short, yes there is a better way to handle it. The 'how' of it is up to you.
Exception handling in C# goes from the most specific exception type to the least specific. Also, you aren't limited to using just one catch block. You can have many of them.
As an example:
try
{
// Perform some actions here.
}
catch (Exception exc) // This is the most generic exception type.
{
// Handle your exception here.
}
The above code is what you already have. To show an example of what you may want:
try
{
// Perform some actions here.
}
catch (SqlException sqlExc) // This is a more specific exception type.
{
// Handle your exception here.
}
catch (Exception exc) // This is the most generic exception type.
{
// Handle your exception here.
}
In Visual Studio, it is possible to see a list of (most) exceptions by pressing CTRL+ALT+E.

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

Try Catch handled at top of process

if I do this:
try
{
//code
}
catch (Exception)
{
throw;
}
Does the Exception go up with all its information?
The idea is to handle errors at the top of the app. There I'd execute some SQL sp to fill the admin's table so he's aware of exceptions.
I want to store Exception.Message and the source (method, function, whatever..) of the exception. But I don't know how to refer to "where" the exception happened. Is it Exception.Source? Exception.TargetSite?
Thanks.
The type of Exception will tell you what kind of exception it is (IndexOutOfRangeException, SqlException, etc) which you would react too accordingly:
try
{
//code
}
catch (SqlException ex)
{
// Handle code
}
catch (IndexOutOfRangeException ex)
{
// Handle code
}
catch (Exception ex)
{
// Handle code
}
As to where it is happening... you should be enclosing exception-prone areas with a try catch and not large code chunks. This way you will know where the exception derives from.
The Short answer is yes: just calling throw passes everthing regarding the exception up.
throw ex resets the stack trace (so your errors would appear to originate from HandleException)
throw doesn't - the original offender would be preserved.
(quoted from Mark Gravell)

Wrong line number on stack trace

I have this code
try
{
//AN EXCEPTION IS GENERATED HERE!!!
}
catch
{
SqlService.RollbackTransaction();
throw;
}
Code above is called in this code
try
{
//HERE IS CALLED THE METHOD THAT CONTAINS THE CODE ABOVE
}
catch (Exception ex)
{
HandleException(ex);
}
The exception passed as parameter to the method "HandleException" contains the line number of the "throw" line in the stack trace instead of the real line where the exception was generated. Anyone knows why this could be happening?
EDIT1
Ok, thanks to all for your answers. I changed the inner catch for
catch(Exception ex)
{
SqlService.RollbackTransaction();
throw new Exception("Enrollment error", ex);
}
Now I have the correct line on the stack trace, but I had to create a new exception. I was hoping to find a better solution :-(
EDIT2
Maybe (if you have 5 minutes) you could try this scenario in order to check if you get the same result, not very complicated to recreate.
Yes, this is a limitation in the exception handling logic. If a method contains more than one throw statement that throws an exception then you'll get the line number of the last one that threw. This example code reproduces this behavior:
using System;
class Program {
static void Main(string[] args) {
try {
Test();
}
catch (Exception ex) {
Console.WriteLine(ex.ToString());
}
Console.ReadLine();
}
static void Test() {
try {
throw new Exception(); // Line 15
}
catch {
throw; // Line 18
}
}
}
Output:
System.Exception: Exception of type 'System.Exception' was thrown.
at Program.Test() in ConsoleApplication1\Program.cs:line 18
at Program.Main(String[] args) in ConsoleApplication1\Program.cs:line 6
The work-around is simple, just use a helper method to run the code that might throw an exception.
Like this:
static void Test() {
try {
Test2(); // Line 15
}
catch {
throw; // Line 18
}
}
static void Test2() {
throw new Exception(); // Line 22
}
The underlying reason for this awkward behavior is that .NET exception handling is built on top of the operating system support for exceptions. Called SEH, Structured Exception Handling in Windows. Which is stack-frame based, there can only be one active exception per stack frame. A .NET method has one stack frame, regardless of the number of scope blocks inside the method. By using the helper method, you automatically get another stack frame that can track its own exception. The jitter also automatically suppresses the inlining optimization when a method contains a throw statement so there is no need to explicitly use the [MethodImpl] attribute.
"But throw; preserves the stack trace !! Use throw; "
How many times have you heard that... Well anyone who has been programming .NET for a while has almost certainly heard that and probably accepted it as the be all and end all of 'rethrowing' exceptions.
Unfortunately it's not always true. As #hans explains, if the code causing the exception occurs in the same method as the throw; statement then the stack trace gets reset to that line.
One solution is to extract the code inside the try, catch into a separate method, and another solution is to throw a new exception with the caught exception as an inner exception. A new method is slightly clumsy, and a new Exception() loses the original exception type if you attempt to catch it further up the call stack.
I found a better description of this problem was found on Fabrice Marguerie's blog.
BUT even better there's another StackOverflow question which has solutions (even if some of them involve reflection):
In C#, how can I rethrow InnerException without losing stack trace?
As of .NET Framework 4.5 you can use the ExceptionDispatchInfo class to do this without the need for another method. For example, borrowing the code from Hans' excellent answer, when you just use throw, like this:
using System;
class Program {
static void Main(string[] args) {
try {
Test();
}
catch (Exception ex) {
Console.WriteLine(ex.ToString());
}
Console.ReadLine();
}
static void Test() {
try {
throw new ArgumentException(); // Line 15
}
catch {
throw; // Line 18
}
}
}
It outputs this:
System.ArgumentException: Value does not fall within the expected range.
at Program.Test() in Program.cs:line 18
at Program.Main(String[] args) in Program.cs:line 6
But, you can use ExceptionDispatchInfo to capture and re-throw the exception, like this:
using System;
class Program {
static void Main(string[] args) {
try {
Test();
}
catch (Exception ex) {
Console.WriteLine(ex.ToString());
}
Console.ReadLine();
}
static void Test() {
try {
throw new ArgumentException(); // Line 15
}
catch(Exception ex) {
ExceptionDispatchInfo.Capture(ex).Throw(); // Line 18
}
}
}
Then it will output this:
System.ArgumentException: Value does not fall within the expected range.
at Program.Test() in Program.cs:line 15
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at Program.Test() in Program.cs:line 18
at Program.Main(String[] args) in Program.cs:line 6
As you can see, ExceptionDispatchInfo.Throw appends additional information to the stack trace of the original exception, adding the fact that it was re-thrown, but it retains the original line number and exception type. See the MSDN documentation for more information.
Does the date/time stamp of your .pdb file match your .exe/.dll file? If not, it could be that the compilation is not in "debug mode" which generates a fresh .pdb file on each build. The pdb file has the accurate line numbers when exceptions occur.
Look into your compile settings to make sure the debug data is generated, or if you're in a test/production environment, check the .pdb file to make sure the timestamps match.
C# stack traces are generated at throw time, not at exception creation time.
This is different from Java, where the stack traces are filled at exception creation time.
This is apparently by design.
I often get this in production systems if Optimize code is checked.
This screws up line numbers even in 2016.
Make sure your configuration is set to 'Release' or whatever configuration you are building and deploying under. The checkbox has a different value per configuration
I never ultimately know how more 'optimized' my code is with this checked - so check it back if you need to - but it has saved my stack trace on many occasions.

Categories

Resources