My Entity Framework will always targeting SQL Server.
So, in my program. What type of exception shall I catch?
DataException or SqlException ?
and in DAL, is it good to throw the exception again after logging?
I would suggest multiple catch and log both.
In live environment its not recommended to throw error to client system, however you always need to throw the error.
So its your call how to do it.
If its live show a beautiful error to client that something went wrong and we are looking.
Related
I'm used to working with SQL database, I'm new to Realm and, so far, I'm really impressed by the ease of use of this new mobile database.
But there is something that I really don't undestand: how to handle error throwing?
Take this simple example:
I want to store in a Realm DB some market stocks.
Each stock has a "symbol" as a unique identifier: APPL for Apple Inc, TSLA for Tesla Motors Inc, etc.
I believe it would make sense to declare these symbols as primary keys, since it's not possible to have multiple times the same symbol in the database
When user clicks on a symbol (among a list of symbols), this symbol is saved in db.
In this Raywenderlich tutorial, it is said: "To simplify the code required in this tutorial, you’ll be used try! when calling Realm methods that throw an error. In your own code, you should really be using try and do / catch to catch errors and handle them appropriately."
So according to the following pattern:
do {
try realm.write {
realm.add(symbol)
}
}
catch let error as NSError {
print("Something went wrong: \(error.localizedDescription)")
}
So far it makes sense.
And if a user clicks on a symbol that is already in the database, I get (very logically) an error:
*** Terminating app due to uncaught exception 'RLMException', reason: 'Can't set primary key property 'symbol' to existing value 'APPL'.'
The problem is that this error is not catched during run time: I've got a crash instead.
My question is not about how to avoid such a crash, I understand of course that it's easy to avoid it by doing a simple testing before writing anything in the database :)
My question is how do we do in Realm to catch potential writing errors?
Am I doing something wrong?
do/try/catch in Swift catch Swift Errors, which are an entirely distinct thing from Objective-C exceptions. Realm follows Foundation's pattern for error reporting: API misuse errors throw exceptions which are not intended to be caught (and can't be caught in Swift), and recoverable errors throw Swift errors (or use NSError out parameters in Objective-C).
Adding an object with a duplicate primary key is considered API misuse, so it's a fatal error as the route for "handling" it is to fix the bug in your code. An example of a recoverable error which would produce a Swift error that would be caught by catch is running out of disk space while trying to save the new data.
There are two distinct types of error: programmer error, and expected errors. Realm handles these two types of errors differently.
Programmer error covers cases such as accessing objects from incorrect threads, out-of-bounds collection access, attempting to insert an object with a duplicate primary key, and so forth. Realm responds to these programmer errors by throwing an Objective-C exception. These exceptions are not intended to be caught and handled as they're indicative of a bug in a Realm user's code.
Expected errors cover things like files not existing, permission errors, failures to write to disk. These are things that can happen even with correctly-written code due to factors outside of the programs control. These are exposed as NSErrors and can be caught from Swift using do / try / catch. Note that Realm's Objective-C API has some convenience methods that don't expose the NSError. In these cases an expected error will throw an exception as there's no other avenue for Realm to communicate the failure. Rather than attempting to catch and handle exceptions raised by these convenience methods, you should use the variant of the API that returns an NSError instead.
Hi, the error line said "to existing value", don't you try to write more than one time the same primary key with 'APPL' ?
you need to update it, not override.
if you try to "add" again the same value, it's gonna stop you.
(sorry for bad english x) )
For the last two years we've been developing a web based application with ASP.NET MVC 3, NHibernate (v. 3.3.1.4000) and PostgreSql for back-end database, therefore using the Npgsql driver (v. 2.0.12.0). The system has been in successful exploitation on 4 different client servers and has never produced the error I encountered on a new server we setup recently. The exception has occurred only once, upon the initial population with data, and prevented some business entities from being stored to the DB. I really must make sure that in the future the error is properly handled, if not at all possible to be avoided, but am at a loss how. Searching the site and the internet in general for this or similar errors has produced no information. Has any of you encountered this problem or have an idea how to fix it? Thanks :)
Here's the error:
System.NotSupportedException: This stream does not support seek operations.
at System.Net.Sockets.NetworkStream.Seek(Int64 offset, SeekOrigin origin)
at System.IO.BufferedStream.FlushRead()
at System.IO.BufferedStream.WriteByte(Byte value)
at Npgsql.NpgsqlSync.WriteToStream(Stream outputStream)
at Npgsql.NpgsqlReadyState.SyncEnum(NpgsqlConnector context)
at Npgsql.NpgsqlState.Sync(NpgsqlConnector context)
at Npgsql.ForwardsOnlyDataReader.GetNextResponseObject()
at Npgsql.ForwardsOnlyDataReader.GetNextRowDescription()
at Npgsql.ForwardsOnlyDataReader.NextResult()
at Npgsql.ForwardsOnlyDataReader..ctor(IEnumerable`1 dataEnumeration, CommandBehavior behavior, NpgsqlCommand command, NotificationThreadBlock threadBlock, Boolean synchOnReadError)
at Npgsql.NpgsqlCommand.GetReader(CommandBehavior cb)
at Npgsql.NpgsqlCommand.ExecuteNonQuery()
at NHibernate.AdoNet.AbstractBatcher.ExecuteNonQuery(IDbCommand cmd)
at NHibernate.AdoNet.NonBatchingBatcher.AddToBatch(IExpectation expectation)
at NHibernate.Persister.Entity.AbstractEntityPersister.Insert(Object id, Object[] fields, Boolean[] notNull, Int32 j, SqlCommandInfo sql, Object obj, ISessionImplementor session)
at NHibernate.Persister.Entity.AbstractEntityPersister.Insert(Object id, Object[] fields, Object obj, ISessionImplementor session)
at NHibernate.Action.EntityInsertAction.Execute()
at NHibernate.Engine.ActionQueue.Execute(IExecutable executable)
at NHibernate.Engine.ActionQueue.ExecuteActions(IList list)
at NHibernate.Engine.ActionQueue.ExecuteActions()
at NHibernate.Event.Default.AbstractFlushingEventListener.PerformExecutions(IEventSource session)
at NHibernate.Event.Default.DefaultFlushEventListener.OnFlush(FlushEvent event)
at NHibernate.Impl.SessionImpl.Flush()
at NHibernate.Transaction.AdoTransaction.Commit()
Since the stack trace originates from NHibernate.Transaction.AdoTransaction.Commit, that means this error was probably logged by NHibernate itself. Your application must do its own logging so that you can have...
details for errors that occur outside of NHibernate
better context for errors that bubble up from NHibernate, like the one you've encountered
See "log all unhandled application errors" and "exception handling should never hide issues" for help on implementing this type of logging.
Without more information about the code that generated this error, this will be nearly impossible to fix. Fixing the logging and exception handling code needs to be one of the top priorities when working with a new code base in order to actually have a fighting chance to fix bugs and improve the code.
This seems to be a bug inside Npgsql.
According to the stacktrace (and checking Npgsql code: https://github.com/npgsql/Npgsql/blob/master/src/Npgsql/NpgsqlDataReader.cs#L1163), when an error occurs inside the GetNextResponseObject(), Npgsql sends a Sync message to server to reset the conversation to a consistent state. The problem is that when this error occurs, some data may have been left in the stream and when Npgsql tries to write to it, the buffered stream checks if there is data yet and, while flushing the data, tries to call seek which isn't supported by a network stream ( over which the buffered stream is created ).
A possible fix for this bug is to flush the buffered stream from any possible data left before writing to it.
I'll create a pull request with this change.
The biggest problem is that this type or error is very rare, as you noticed. This error occurred only once for you. I'll need to investigate more what have caused the exception to be thrown in the first place.
I hope it helps.
The most popular desicion for handling exceptions in rest service and return the error message to client - as i understand - is to catch WebApplicationException or MappableContainerException. But they are extending RuntimeExceprion (I don't understand why). As I know we should avoid handling RuntimeExceptions.
I need to handle such exceptions as "The entity with such name already exsists". I'm sure it is not a runtime exception.
Any other ways? I'm researching now Wrappers. May be you could excplain me the best way to solve my problem?
The way that I handle this is to have my own exception hierarchy, and to build a separate ExceptionMapper which handles this hierarchy. That allows me to pass back whatever information I need to (in my case a JSON-formatted response) in a standardized way.
I would still have an ExceptionMapper for WebApplicationException, otherwise the end user might receive some nasty looking responses. And if you want to be extra-safe then you can also put one in for Exception that picks up anything else you might have missed (the exceptions go to the most specific exception mapper for them, so putting one in for Exception doesn't affect them).
I know that when there is an unhandled Exception in asmx that it generates a soapFault and returns it to the client. What I want to know is if there is a way to return a soapFault without throwing an exception. Throwing an exception is an expensive operation and I would like to avoid it if I can.
AFAIK there is no such option (short from building the complete XML/SOAP message yourself that is)... with WCF this could be slightly easier IMO
You can throw a SoapException and can customize it rather thoroughly:
http://support.microsoft.com/kb/833379/en-us
http://msdn.microsoft.com/en-us/library/aa480514.aspx
Many of the Caché API methods return a %Status object which indicates if this is an error. The thing is, when it's an unknown error I don't know how to handle (like a network failure) what I really want to do is "throw" the error so my code stops what it's doing and the error gets caught by some higher level error handler (and/or the built-in %ETN error log).
I could use ztrap like:
s status = someObject.someMethod()
ztrap:$$$ISERR(status)
But that doesn't report much detail (unlike, say, .NET where I can throw an exception all the way to to the top of the stack) and I'm wondering if there are any better ways to do this.
Take a look at the Class Reference for %Exception.StatusException. You can create an exception from your status and throw it to whatever error trap is active at the time (so the flow of control would be the same as your ZTRAP example), like this
set sc = someobj.MethodReturningStatus()
if $$$ISERR(sc) {
set exception = ##class(%Exception.StatusException).CreateFromStatus(sc)
throw exception
}
However, in order to recover the exception information inside the error trap code that catches this exception, the error trap must have been established with try/catch. The older error handlers, $ztrap and $etrap, do not provide you with the exception object and you will only see that you have a <NOCATCH> error as the $ZERROR value. Even in that case, the flow of control will work as you want it to, but without try/catch, you would be no better off than you are with ZTRAP
These are two different error mechanisms and can't be combined in this way. ztrap and %ETN are for Cache level errors (the angle bracket errors like <UNDEFINED>). %Status objects are for application level errors (including errors that occurred through the use of the Cache Class Library) and you can choose how you want to handle them yourself. It's not really meaningful to handle a bad %Status through the Cache error mechanism because no Cache error has occurred.
Generally what most people do is something akin to:
d:$$$ISERR(status) $$$SomeMacroRelevantToMyAppThatWillHandleThisStatus(status)
It is possible to create your own domain with your own whole host of %Status codes with attendant %msg values for your application. Your app might have tried to connect to an FTP server and had a bad password, but that doesn't throw a <DISCONNECT> and there is no reason to investigate the stack, just an application level error that needs to be handled, possibly by asking the user to enter a new password.
It might seem odd that there are these two parallel error mechanisms, but they are describing two different types of errors. Think of one of them being "platform" level errors, and the other as "application level errors"
Edit: One thing I forgot, try DecomposeStatus^%apiOBJ(status) or ##class(%Status).LogicalToOdbc(status) to convert the status object to a human readable string. Also, if you're doing command line debugging or just want to print the readable form to the principal device, you can use $system.OBJ.DisplayError(status).