Where should I be logging exceptions? At the data service tier(ExecuteDataSet, etc.) and/or at the data access layer and/or at the business layer?
If you are throwing the exception you should log it when it occurs and then bubble it up. Otherwise only the end user should log an exception (you may have lots of tracing on of course in which case it may get logged quite a bit).
The end user may be a UI component or a Service or something...
If you handle an exception in you code somewhere - then that is the end user and you should log it there. In most apps and in most cases it should be logged by the UI when it displays the error message to the user.
At a physical tier boundary.
Also in the top-level exception handler in the client.
I.e. if your business tier is running on a server, log exceptions before propagating to the client. This is easy if you're exposing your business tier as WCF web services, you can implement an error handler that does the logging before propagating a SOAP fault to the client.
I usually allow exceptions to propagate up and log them when they reach the very top level. For example
main {
try {
application code
} catch {
preform logging
}
}
But that only makes sense for fatal exceptions. Other exceptions I usually log them in the block that handles the recover from said exception.