2009-07-16 11 views
1

Puis-je obtenir l'objet qui a causé une exception GenericADOException (exception de contrainte)?NHibernate/Castle activeecord: Comment obtenir l'objet qui a provoqué une exception de base de données?

Ou Comment est-ce que je peux seulement vider un objet afin que je puisse dire quel est le problème.

J'ai une liste d'objets qui sont affichés dans un formulaire, et peuvent être modifiés et ajoutés à. Sur flush, il me donne une exception de base de données, mais je ne peux pas dire quel objet a donné l'exception.

Je ne peux pas déplacer la contrainte à nhiber.

Répondre

0

Par googling je suis arrivé à un poste qui a été utile, puis en lisant la source NHibernate je suis arrivé à ce qui suit:

http://fabiomaulo.blogspot.com/2009/06/improving-ado-exception-management-in.html


'http://fabiomaulo.blogspot.com/2009/06/improving-ado-exception-management-in.html 
'properties.Add("sql_exception_converter", "SmartCore.SmartDatabaseExceptionConverter, SmartCore") 
Class SmartDatabaseExceptionConverter 
    Implements ISQLExceptionConverter 


    Public Function Convert(ByVal sqlException As System.Exception, ByVal message As String, ByVal sql As NHibernate.SqlCommand.SqlString) As NHibernate.ADOException Implements NHibernate.Exceptions.ISQLExceptionConverter.Convert 

     Dim sqle As DbException 
     sqle = ADOExceptionHelper.ExtractDbException(sqlException) 
     '"could not update: [SmartCore.GL.Glaccount#1225]" 
     Dim obname As String 
     Dim key As String 
     obname = ExtractUsingTemplate("could not update: [", "#", message) 
     key = ExtractUsingTemplate("#", "]", message) 

     Dim prikey As Integer 
     prikey = Integer.Parse(key) 

     sqle.Data.Add("obname", obname) 
     sqle.Data.Add("prikey", key) 

     If sqle.ErrorCode = 335544558 Then 
      '"Operation violates CHECK constraint C_GLACCOUNT on view or table GLACCOUNT At trigger 'CHECK_56'" 
      Dim checkname As String 
      checkname = ExtractUsingTemplate("Operation violates CHECK constraint ", "on view or table ", sqle.Message) 
      Return New SmartDatabaseConstraintException(message, sqle, obname, prikey, checkname) 
      'Return New ConstraintViolationException(message, sqle, sql, checkname) 
     End If 

     Return SQLStateConverter.HandledNonSpecificException(sqlException, message, sql) 
    End Function 



    Protected Function ExtractUsingTemplate(ByVal templateStart As String, ByVal templateEnd As String, ByVal message As String) As String 
     Dim templateStartPosition As Integer = message.IndexOf(templateStart) 
     If templateStartPosition < 0 Then 
      Return Nothing 
     End If 

     Dim start As Integer = templateStartPosition + templateStart.Length 
     Dim [end] As Integer = message.IndexOf(templateEnd, start) 
     If [end] < 0 Then 
      [end] = message.Length 
     End If 

     Return message.Substring(start, [end] - start).Trim() 

    End Function 
End Class 

'USAGE 
     Try 
      _scope.Flush() 
     Catch ex As SmartDatabaseConstraintException 
      If ex.ConstraintName = "C_GLACCOUNT" Then 
       Dim gla As GL.Glaccount 
       gla = GL.Glaccount.Find(ex.EntityId) 'should be fast from entity cache 
       msgboxError(gla.description & " is duplicate please rename") 
      Else 
       msgboxError(ex.Message) 
      End If 
     End Try 

Je devais l'adapter pour travailler avec ma version nhibernate légèrement obsolète (2.1 de mars) Je vais devoir adapter légèrement ce qui précède pour travailler avec des versions plus récentes où il y a un AdoExceptionContextInfo à partir duquel on peut obtenir le nom et l'ID de l'objet. Nhibernate est bon!

0

Avez-vous essayé d'utiliser NHibernate Profiler? Cela devrait vous donner des détails supplémentaires sur le problème.

+0

Je sais par œil qui est à l'origine du problème, le problème est de savoir comment le déterminer par code. J'ai besoin de savoir dans le code quel objet donne le problème afin que je puisse le modifier ou le supprimer. Pensez à une contrainte unique dans la base de données. – AngelBlaZe

+0

Bien que je comprenne que NHibernate est assez extensible et il est probable que vous pourriez obtenir cette information de NH Je doute que ce sera facile. À ce stade, vous avez deux options. 1. Espérons qu'un spécialiste comme Ayende Rahien se présente (douteux - plus probable est de l'embaucher) pour vous dire comment 2. Comme vous devriez traiter cela comme une seule unité de travail (d'où il est dans une transaction) appelant vider manuellement pour chaque mise à jour semble être une option plus probable pour moi. –

+0

Savez-vous comment vider manuellement un objet? comme dans dire à une session de vider seulement cet objet. J'ai une liste d'entre eux et d'être changé par liaison de données sur un formulaire Windows, donc je n'ai aucun contrôle de quand ils changent comme on peut dans le web. – AngelBlaZe

Questions connexes