I have mapped classes with custom sql (insert, delete, update) through procedure calls. But, I noticed that when my insert procedure fails raising exception, the GenericAdoException from NHibernate doesn’t have my message raised from the procedure.
But, all raised exceptions from procedures for delete and update is catched well, only the insert procedure hasn’t its exception message catched.
Is that a limitation or a bug of NHibernate 3.2.4 when we use “native” generator for ids combined with custom sql ?
I’m searching also ways to get some out parameters from that procedures like a timestamp to each event (insert, delete and update), the timestamp is generated inside procedures.
EDIT: OUT PARAMs – I found the “generated” option over properties mapping options which we can ask to NHibernate to get params from procedures. This means that these properties have genarated values. So I tried to use generated=”always” and works for insert, update and delete operations. Example: <property name="MyProp" generated="always"/>
I found that sql server driver doesn’t put the messages raised by stored procedures into the SqlException when you run these stored procedures with
ExecuteReader(). On the other hand NHibernate executes the custom sql-insert withExecuteReader()(I debbuged its source code) and I guess it’s right and necessary to get the key when it’s mapped with native (or identity), my case.Well, and now what to do ? I found also (hard to found) that the SqlConnection has a event called “InfoMessage” in which you can receive (catch) all messages sent from your stored procedures (raiserror). Now this is possible to “catch” these messages, but how to make them cross NHibernate core and be received by our application when we insert something
session.save()?Altough we have access to session and so to the connection (SqlConnection) the messages was already lost, because them are only received by the delegate assigned to the event
SqlConnection.InfoMessagebefore of its occurrence.To solve this, I tried two approaches:
DriverConnectionProvider.GetConnection()and this delegate would store the messages on the thread context associating it with the connection, so these messages could be getted later.IDbConnectionandIDbCommandwrapping inside them theSqlConnectionandSqlCommand(but I think the NHibernate has a bug because in some places it references DbConnection instead IDbConnection – like in ManagedProviderConnectionHelper, so I had to extend from DbConnection and DbCommand instead).Inside my CustomSqlConnection I register the delegate and store the messages for later use.
This is working ! Work as standalone driver (ADO) either as a NHibernate driver.
The idea is:
EDIT: The hard step is to implement all operations from DdConnection and Dbcommand, repassing the call to the sql instance (look the field
conabove), so: