I have a .NET web application that frequently executes queries to get data from a local database.
In situations where the query doesn't run (due to an exception) or the query returns an unexpected set of data (such as an empty set). I want to be able to rebuild the query (replacing it's #parameters with the values actually used) and store the complete query in the database along with the exception.
I'm aware that I can do this through standard code but I was wondering whether it would be safer to do via Elmah?
Also would doing this via Elmah give me the ability to be able to view the executed sql through elmah.axd (when access is enabled)?
Unless the thrown exception includes the query with the actual values, ELMAH doesn't help you there other than logging the exception. You can catch the exception yourself and do a custom logging to ELMAH using the ErrorSignal.Raise method as explained here: How to use ELMAH to manually log errors?
I log SQL exceptions by passing the exception and the actual command to a new Exception class. The class wraps the SqlException and the System.Data.Common.DbCommand objects. Using that information I can create a message to provide the sql command details:
public override string Message
{
get
{
StringBuilder message = new StringBuilder("");
StringBuilder sql = new StringBuilder("");
sql.AppendFormat(" {0} ", Command.CommandText);
foreach (SqlParameter param in Command.Parameters)
{
sql.AppendFormat(" {0} - {1}", param.ParameterName,
param.Value.ToString());
}
message.AppendFormat("Error: {0} SQL: {1} User: {2}", SqlEx.Message,
sql, Username);
return message.ToString();
}
}
Finally, I use the ErrorSignal Raise method to log the message in Elmah:
Elmah.ErrorSignal.FromCurrentContext().Raise(new DetailSqlException(e.Exception as SqlException, e.Command, user));
Related
I'm writing a small, simple web app in go using the gorm ORM.
Since the database can fail independently of the web application, I'd like to be able to identify errors that correspond to this case so that I can reconnect to my database without restarting the web application.
Motivating example:
Consider the following code:
var mrs MyRowStruct
db := myDB.Model(MyRowStruct{}).Where("column_name = ?", value).First(&mrs)
return &mrs, db.Error
In the event that db.Error != nil, how can I programmatically determine if the error stems from a database connection problem?
From my reading, I understand that gorm.DB does not represent a connection, so do I even have to worry about reconnecting or re-issuing a call to gorm.Open if a database connection fails?
Are there any common patterns for handling database failures in Go?
Gorm appears to swallow database driver errors and emit only it's own classification of error types (see gorm/errors.go). Connection errors do not currently appear to be reported.
Consider submitting an issue or pull request to expose the database driver error directly.
[Original]
Try inspecting the runtime type of db.Error per the advice in the gorm readme "Error Handling" section.
Assuming it's an error type returned by your database driver you can likely get a specific code that indicates connection errors. For example, if you're using PostgreSQL via the pq library then you might try something like this:
import "github.com/lib/pq"
// ...
if db.Error != nil {
pqerr, ok := err.(*pq.Error)
if ok && pqerr.Code[0:2] == "08" {
// PostgreSQL "Connection Exceptions" are class "08"
// http://www.postgresql.org/docs/9.4/static/errcodes-appendix.html#ERRCODES-TABLE
// Do something for connection errors...
} else {
// Do something else with non-pg error or non-connection error...
}
}
My Grails application is not using GORM but instead uses my own SQL and DML code to read and write the database (The database is a huge normalized legacy one and this was the only viable option).
So, I use the Groovy Sql Class to do the job. The database calls are done in Services that are called in my Controllers.
Furthermore, my datasource is declared via DBCP in Tomcat - so it is not declared in Datasource.groovy.
My problem is that I need to write some transaction code, that means to open a transaction and commit after a series of successful DML calls or rollback the whole thing back in case of an error.
I thought that it would be enough to use groovy.sql.Sql#commit() and groovy.sql.Sql#rollback() respectively.
But in these methods Javadocs, the Groovy Sql documentation clearly states
If this SQL object was created from a DataSource then this method does nothing.
So, I wonder: What is the suggested way to perform transactions in my context?
Even disabling autocommit in Datasource declaration seems to be irrelevant since those two methods "...do nothing"
The Groovy Sql class has withTransaction
http://docs.groovy-lang.org/latest/html/api/groovy/sql/Sql.html#withTransaction(groovy.lang.Closure)
public void withTransaction(Closure closure)
throws java.sql.SQLException
Performs the closure within a transaction using a cached connection. If the closure takes a single argument, it will be called with the connection, otherwise it will be called with no arguments.
Give it a try.
Thanks James. I also found the following solution, reading http://grails.org/doc/latest/guide/services.html:
I declared my service as transactional
static transactional = true
This way, if an Error occurs, the previously performed DMLs will be rolled back.
For each DML statement I throw an Error describing the message. For example:
try{
sql.executeInsert("""
insert into mytable1 (col1, col2) values (${val1}, ${val2})
""")
catch(e){
throw new Error("you cant enter empty val1 or val2")
}
try{
sql.executeInsert("""
insert into mytable2 (col1, col2) values (${val1}, ${val2})
""")
catch(e){
throw new Error("you cant enter empty val1 or val2. The previous insert is rolledback!")
}
Final gotcha! The service when called from the controller, must be in a try catch, as follows:
try{
myService.myMethod(params)
}catch(e){
//http://jts-blog.com/?p=9491
Throwable t = e instanceof UndeclaredThrowableException ? e.undeclaredThrowable : e
// use t.toString() to send info to user (use in view)
// redirect / forward / render etc
}
i am trying to retrieve data from database via nhibernate's CreateSQLQuery on a stored proceduure. Something like the following code.
then I am basically doing a session transaction commit, however the commit throws an "cannot update" exception. It is trying to execute a update statement on CustomEntityDao.
const string selectSQL = "EXEC GetDataSP #Id = :Id";
var query = Session.CreateSQLQuery(selectSQL);
query.SetString("Id", "10");
query.AddEntity(typeof (CustomEntityDao));
var entityList = query.List<CustomEntityDao>();
try
{
Session.Transaction.Commit();
}
catch (Exception ex)
{
throw ex;
}
My question is why are the entities been treated as modified, as you can see in the code I am only doing a query.
May be there is something else going on your code, what I can suggest is use NHibernate Profiler a trial version of which can be downloaded from www.nhprof.com and monitor the SQL commands that are being fired and notice what objects are being retrieved.
Also I dont understand why are you committing the transaction in the first place.
To solve this particular problem you could always use NHibernates StatelessSession which doesnt track entities or you can also use Session.Evict and ask Nhibernate to stop tracking particular objects.
I am using linq-to-entity to retrieve data dynamically and created a method as follows:
public List<object> getDynamicList(string tablename, List<string> colnames)
{
try
{
var query = DynamicQueryable.getDynamicData(dbcontext, tablename, colnames);
List<object> objQueryable = new List<object>();
object obj = query.AsQueryable();
objQueryable.Add(obj);
return objQueryable;
}
catch (Exception ex)
{
HandleError(ex);
}
}
this method in wcf service internally refers dynamic class given in LINQ samples (C:\Program Files (x86)\Microsoft Visual Studio 10.0\Samples\1033)by MSVS2010.
when i am passing tablename,columns dynamically it does but on client side,while consuming that method it gives error- The server did not provide a meaningful reply; this might be caused by a contract mismatch, a premature session shutdown or an internal server error.
does wcf gives issue with iqueryable return type ?
please suggest......
You should look into WCF Data Services aka oData Services
Try using returning ToList() instead because Linq uses concept of Deffer Loading which means when at client side ToList or Result is being accessed it tries to connect to Server for getting result and it is where it would be getting failed. It is recommended when you use such kind of ORM you detach your objects and send result to client.
What's the best practice for handling exceptions in NHibernate?
I've got a SubjectRepository with the following:
public void Add(Subject subject)
{
using (ISession session = HibernateUtil.CurrentSession)
using (ITransaction transaction = session.BeginTransaction())
{
session.Save(subject);
transaction.Commit();
}
}
And a Unit Test as follows:
[Test]
public void TestSaveDuplicate()
{
var subject = new Subject
{
Code = "En",
Name = "English"
};
_subjectRepository.Add(subject);
var duplicateSubject = new Subject
{
Code = "En",
Name = "English1"
};
_subjectRepository.Add(duplicateSubject);
}
I got to the point of handling the error generated by the unit test and got a bit stuck. This fails as expected, though with a GenericADOException, I was expecting a ConstraintViolationException or something similar (there is a uniqueness constraint on the subject code at database level).
The ADOException wraps a MySQL Exception that has a sensible error message but I don't want to start breaking encapsulation by just throwing the inner exception. Particularly as MySQL isn't finalised as the back end for this project.
Ideally I'd like to be able to catch the exception and return a sensible error to the user at this point. Are there any documented best practice approaches to handling NHibernate Exceptions and reporting back up to the user what went wrong and why?
Thanks,
Matt
I would handle it in the Add method as such:
public void Add(Subject subject)
{
using (ISession session = HibernateUtil.CurrentSession)
using (ITransaction transaction = session.BeginTransaction())
{
try
{
session.Save(subject);
transaction.Commit();
}
catch (Exception ex)
{
transaction.Rollback();
// log exception
throw;
}
}
}
In the catch block, you should first rollback the transaction and log the exception. Then your options are:
Rethrow the same exception, which is what my version does
Wrap it in your own exception and throw that
Swallow the exception by doing nothing, which is very rarely a good idea
You don't have any real options for handling the exception in this method. Assuming that the UI calls this method, it should call it in its own try..catch and handle it by displaying a meaningful error message to the user. You can make your unit test pass by using the ExpectedException(type) attribute.
To answer your question directly, you should create your own "sensible error" by extending Exception and throw that with the original exception as its InnerException. That's the exception wrapping technique I listed in (2).
All the Nhibernate exceptions are non recoverable, you could revisit the design of the app/data layer if you are trying to recover from nhibernate exceptions .
You can also Take a look at spring.net 's exception translation implementaion
Also you manually handling transactions on exceptions is tedious and error prone, take a look at nhibernate's contextual sessions .
Spring.net also has some nice helpers around nhibernate .
The general question is going to be, what do you want to tell the user, and who is the user?
If the user will sometimes be another computer (i.e., this is a web service), then you would want to use the appropriate mechanism to return a SOAP Fault or HTTP error.
If the user will sometimes be a UI of some sort, then you may want to display a message to the user, but what would you tell the user so he can do something about it? For instance, most web sites will say, "sorry, we had an unexpected error", no matter what the reason. That's because there's usually nothing the user could do about the error.
But in either case, the choice of how to tell "the user" is a matter for the Presentation layer (UI tier), not for the DAL. You should possibly wrap exceptions from the DAL in another exception type, but only if you're going to change the message. You don't need your own exception class, unless your callers would do something different if it's a data access exception rather than some other kind.
I'd probably validate the input before saving the object; that way you can implement whatever validation you like (e.g. check the length of the Subject Code as well as the fact that there aren't any duplicates), and pass back meaningful validation errors back to the user.
The logic is as follows; exceptions are used to indicate exceptional circumstances that your program doesn't cater for. A user entering a duplicate Subject Code in your example above is something your program should be catering for; so, rather than handling an exception because a DB constraint gets violated (which is an exceptional event and shouldn't be occurring), you'd want to handle that scenario first and only attempt to save the data when you know that the data you're saving is correct.
The advantage with implementing all validation rules in your DAL is that you can then ensure that the data going into your DB is valid as per your business processes in a consistent manner, rather than relying on the constraints in your DB to catch those for you.