I am trying to get the number of the try attempt of a SQLConnection to inform the user about those attempts.
Below you can see the code, where magic should happen. 'i' would be the number of the attempt. The connection 'con' throws a lot of SqlExceptions, but i can't catch them like shown below. 'databaseConnection' represents the connectionstring. It is currently empty for testing purposes.
I bet, that i am missing something, but I can't figure out what, since I'm new to SQL programming in C#.
"txtProgressbarWorking" is a label in the UI.
int i = 1;
con = new SqlConnection(databaseConnection);
try
{
con.Open();
}
catch(SqlException s)
{
txtProgressbarWorking.Content = "Connecting... " + (++i);
}
There are several things wrong with this code:
1) Are you calling this in some sort of loop? If not, your i variable won't be incremented.
2) SqlConnection.Open() throws several kinds of exceptions - not just SqlException, which I assume is why you "can't catch them" all as you mentioned. You should ideally specify each exception or catch the higher-level System.SystemException.
3) Your code to increment the progress bar is in the catch-block of your exception handler, and will only be executed if the exception is caught. If you are in fact calling this code in a loop, you would want to move the code in the catch-block into the try-block instead.
4) Your ++i should be i++ so that i is incremented after the statement; either that, or initialize i to zero instead of 1. The way you have it now, the first value from i in your catch-block would be 2.
I suggest you take a look at [MSDN's documentation on SqlConnection.Open Method ()][1]
https://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlconnection.open%28v=vs.110%29.aspx
Related
So I've been doing some work with NHibernate, and while what I have seen is mostly great, one thing is a little frustrating. If I try to query for some objects and there is a mapping problem in or with the hbm file, often there is no indication that there is a mapping problem, it just returns no results.
A simple example is if I forget to set the hbm file as an embedded resource, and then do a session.Query<Variable>().ToList(), there is no indication that there is no mapping for Variable, it just returns an empty list.
Is there any way to tell NHibernate to throw an exception or otherwise indicate that there is a problem with the mapping(s) in situations like this?
This does result in an exception:
_session.Get<Variable>(1)
But these do not:
_session.Query<Variable>().Where(e => e.VariableId == 1).ToList()
_session.CreateCriteria(typeof(Variable)).Add(Restrictions.Eq("VariableId",1)).List<Variable>();
Hopefully it's something that I'm doing wrong, or something that can be configured, otherwise it will probably be a deal-breaker for using NHibernate. I can catch these things in my own unit tests relatively easy, but I can just see this becoming a festival of bugs when other developers start touching it.
After doing a bit of digging through the code, I suspect you are right. Unmapped classes don't throw an exception on a List.
https://github.com/nhibernate/nhibernate-core/blob/master/src/NHibernate/Impl/SessionImpl.cs#L1869
string[] implementors = Factory.GetImplementors(criteria.EntityOrClassName);
int size = implementors.Length;
CriteriaLoader[] loaders = new CriteriaLoader[size];
ISet<string> spaces = new HashSet<string>();
for (int i = 0; i < size; i++)
{
loaders[i] = new CriteriaLoader(
GetOuterJoinLoadable(implementors[i]),
Factory,
criteria,
implementors[i],
enabledFilters
);
spaces.UnionWith(loaders[i].QuerySpaces);
}
Note how if there are no implementors that are returned by Factory.GetImplementors, no error is generated, but nothing is done. Hence why you are seeing an empty list come back.
If we look at SessionFactoryImpl.GetImplementors we see that at no point is an exception thrown if no implementor is found. Just an empty array of implementors is returned.
So potentially there needs to be a check that if no implementors are returned by Factory.GetImplementors, a MappingException needs to be thrown.
In some applications, I came across some lines of code which deliberately eats the exceptions. In my application the benefit of doing this is - To ignore the exception and just continue with the loop(The exception handled is for an error thrown inside the loop). The following lines of code looks evil to even an experienced developers. But is sensible to the context(I mean, that is the requirement - to process all the files in the directory).
try{
//some lines of code which might throw exception
}catch(Exception e){
//no code to handle the error thrown
}
What other benefits can ignoring exceptions provide?
If it is a requirement to process all the files, if you get an exception during processing one of them, is not the requirement broken already? Either something failed or the exception is not needed.
If you want to continue the processing handle the exception, then continue. Why not just report the problem with processing a given file,so someone can later process it manually? Probably even stupid cerr << "Hey I had trouble with this file '" << file <<', so I skipped it.\n" would be better than nothing.
Exception is there to signal something. If you are ignoring it either you are doing something nasty, or the exception is not needed.
The only valid reason for ignoring the exception I can think of is when someone throws exceptions at you for no good reason. Then maybe, yeah, ignore.
This is generally the mark of bad code - you always want to handle your exceptions by at a minimum reporting what the exception is. Ignoring exceptions will let your program keep running, but generally exceptions are thrown for a reason and you or the user need to know what that reason is. Doing a catch-all and escaping just means the coder was too lazy to fix whatever problems cropped up.
The exception is if the coder is throwing exceptions merely to pass arguments, which is something I saw on DailyWTF once.
Usually we should not absorb the exception but there can be reason like there is a function which is out of business logic that is just to help some kind of extra functionality, then you do not want your application to break if that function throw the exception in that case you absorb/eat the exception. But I do not recommend the empty catch block, one should log this in ELMAH or other error logging tools for future.
I don't think there any any benefits of ignoring exceptions. It will only cause problems. If you want the code to be executed in the loop, after handling it, it will continue with the loop because exception is handled. You can always process the files in your directory even if you are not doing anything after handling exceptions.
It will be better if you write some log regarding the files for which exception is thrown
If you eat the exception. You may never know what is the actual cause of the problem.
Considerr this example
public class Test {
private int x;
public void someMethod(){
try {
x = 10/0;
} catch (Exception e) {
}
}
public static void main(String[] args) {
Test test = new Test();
test.someMethod();
System.out.println(test.x);
}
}
This will print simply 0 the default value of x as exception occured during division and value was not assigned to x
Here you are supposed to get actual result of the division. Well it will definitely throw an ArithMeticException because we are dividing by zero and we have not written anything in catch block. So if the exception occurs, nothing will be printed and value of x will be 0 always and we can't know whether the division is happend or not. So always handle exceptions properly.
assume you have a function that polls some kind of queue and blocks for a certain amount of time. If this time has passed without something showing up on the queue, some indication of the timeout should be delivered to the caller, otherwise the something that showed up should be returned.
Now you could write something like:
class Queue
{
Thing GetThing();
}
and throw an exception in case of a timeout. Or you
write
class Queue
{
int GetThing(Thing& t);
}
and return an error code for success and timeout.
However, drawback of solution 1 is that the on a not so busy queue timeout is not an exceptional case, but rather common. And solution 2 uses return values for errors and ugly syntax, since you can end up with a Thing that contains nothing.
Is there another (smart) solution for that problem? What is the preferred solution in an object oriented environment?
I would use exceptions only when the error is serious enough to stop the execution of the application, or of any big-enough application's component. But I wouldn't use exceptions for common cases, after which we continue the normal execution or execute the same function again. This would be just using exceptions for flow control, which is wrong.
So, I suggest you to either use the second solution that you proposed, or to do the following:
class Queue
{
bool GetThing(Thing& t); // true on success, false on failure
string GetLastError();
};
Of course you can stick with an int for an error code, instead of a string for the full error message. Or even better, just define class Error and have GetLastError() return it.
Why not just return null from GetThing in your first solution, changing it to return a Thing *? It seems to fit the bill, at least from the information you've given so far.
In the first, and second case, you can't do anything but throw an exception. When you return a Thing, or a Thing&, you don't have the option of not returning a Thing.
If you want to fail without using an exception then you need:
class Queue
{
// Either something like this. GetThing retuns NULL on an error,
// GetError returns a specific error code
Thing* GetThing();
int GetError();
// This kind of pattern is common. Return a result code
// and set ppOut to a valid thing or NULL.
int GetThing(Thing** ppOut);
};
What are good things to check for, with respect to error-handling, when you are dealing with the data-access-layer? For example, let's assume I have this function..
Public Function UserExists(ByVal userName As String) As DataTable
Dim dt As Object = Nothing
Dim arSqlParameters(0) As SqlParameter
arSqlParameters(0) = New SqlParameter("#UserName", SqlDbType.NVarChar, 50)
arSqlParameters(0).value = userName
dt = ABC.APP.DAL.DALHelper.ExecuteDatatable(ConnectionString, CommandType.StoredProcedure, "dbo.aspnet_sprGetUserByUsername", arSqlParameters)
Return dt
End Function
This seems like very lazy and unsafe coding. How would you go about ensuring that your code elegantly handles anything unexpected in a situation like this?
I'm new to vb.net and the app that I'm working on has no error handling, so I figured this would be the best place to look for advice. Thanks in advance :)
Not sure why you're not declaring dt as a datatable - what is the motiviation for "dim dt as object = nothing"?
Really the only line that can reasonably fail is the "dt=ABC.APP.DAL...." call.
In that line, you could have a few errors:
The stored procedure or parameter
names are wrong. This should be
caught at design-time (not by a
built-in checking mechanism, but the
first time that you try to run the
code)
An error occurs in the stored
procedure. Sprocs use deferred name
resolution, which can lead to runtime
errors if (for instance) objects
don't exist at the time that the
sproc is called. Again, this is most
likely to rear it's head in testing.
A deadlock. In this case, you should
catch and resubmit the batch.
Here's an intro and set of links
on handling SQL errors in application
code.
A parameter that is passed is
invalid (too long, wrong datatype,
etc). This should be checked
before you call the sproc.
This might be of use to you...
.NET Framework Developer's Guide - Design Guidelines for Exceptions
Opinions are likely to vary wildly on a topic like this, but here's my take. Only try to deal with the exceptions that you relate to this area. That's a vague statement, but what I mean is, did the user pass a string with more chars than the column in the db. Or did they violate some other business rule.
I would not catch errors here that imply the database is down. Down this far in the code, You catch errors that you can deal with, and your app needs it's database. Declare a more global exception handler that logs the problem, notifies someone, whatever... and present the user with a "graceful" exit.
I don't see any value in catching in each method a problem with the database. You're just repeating code for a scenario that could bomb any part of your datalayer. That being said, if you choose to catch db errors (or other general errors) in this method, at least set the innerexception to the caught exception if you throw a new exception. Or better, log what you want and then just "throw", not "throw ex". It will keep the original stack trace.
Again, you will get a lot of varying thoughts on this, and there is no clear right and wrong, just preferences.
looking inside Open Source ORM solutions' code (Subsonic, nHibernate) will help you.
By my limited knowledge I think error related to connections, connection timeouts etc. should be passed as such because DAL cannot do much about it. Error related to the validations (like field lengths, datatypes) etc should be returned with appropriate details. You may provide validation methods (Subsonic contains it) that validate the field values and returns the appropriate error details.
I've put a lot of thought into this as well. A lot depends on the particular database, so depending on if you are using SQL2000 or SQL2005+ you will either be doing return codes, RAISERROR or TRY-CATCH in the stored procedure.
RAISERROR is preferably to return codes, because developers using the stored procedure get more information. Optimally you'd pick numbers 50000 and up and register the corresponding messages, but this is a lot of work just to communicate what can be communicated in the text of the RAISERROR call
The return code is uninterperatable without reading the source code of the stored procedure. a return value of 0 might be success, failure, 0 rows affected, the just generated primary key, or that no return code was set depending on the whims of the stored procedure writer that day. Also, ADO.NET returns row count from ExecuteNonQuery, so some developers will find it hard to quickly discover the return code.
Ad hoc solutions are also bad, eg.
IF ##Error>0
SELECT 'Something bad happened'
If you have the option of using CLR stored procedures, then C# style error handling comes into play.
So add RAISERROR to your stored procedures, then catch SqlException, report to the user anything that really is a user data entry Validation, log anything that is a developer abusing the API, and maybe attempt a re-try for connection or execution timeouts.
IF #Foo =42
BEGIN
RAISERROR ( 'Paramater #foo can''t be 42',
16, -- Severity = Misc. User Error.
1 -- State. == ad hoc way of finding line of code that raised error
) ;
RETURN -1; --Just because some developers are looking for this by habit
END
I'm working on modifying this example:
Using advWorksContext As New AdventureWorksEntities
' Call the constructor that takes a command string and ObjectContext.
Dim productQuery1 As New ObjectQuery(Of Product)("Product", advWorksContext)
Dim result As Product
For Each result In productQuery1
Console.WriteLine("Product Name: {0}", result.Name)
Next
End Using
An ObjectQuery can be enumberated only once. (Subsequent attempts at enumeration throw an exception.) The enumberation takes place in the for each statement. The problem is that if the query is empty attempting a For Each will throw an exception. But if I check for a count:
If productQuery1.Count > 0 Then . . .
That eats up my one chance at enumeration. I could nest the For Each in a try/catch block and throw away the empty query exceptions, but that's ugly. Is there a better solution?
If you add a ToList() call to the end of your query, you should be able to enumerate the results as often as you like.