2010-01-25 10 views

Respuesta

94

Puedo ver desde el foro y publicaciones en blogs en todas partes que muchos otros antes que yo han buscado una forma de obtener las declaraciones SQL mientras se preparan para su ejecución. La respuesta generalmente es algo como "no se puede" o "no se debe".

Si debería o no, eso es lo que quería.

Después de horas de búsqueda, investigación e intentos fallidos, y finalmente se me ocurrió esto.

redactar un interceptor:

using NHibernate; 
using System.Diagnostics; 

public class SqlStatementInterceptor : EmptyInterceptor 
{ 
    public override NHibernate.SqlCommand.SqlString OnPrepareStatement(NHibernate.SqlCommand.SqlString sql) 
    { 
     Trace.WriteLine(sql.ToString()); 
     return sql; 
    } 
} 

Por supuesto, usted no tiene que Trace.WriteLine() aquí, se podría escribir en un archivo de registro, o cualquier otra cosa que necesite.

En el administrador de conexión, conectar su interceptor de este modo:

protected virtual void Configure(FluentConfiguration config) 
{ 
    config.ExposeConfiguration(x => 
            { 
             x.SetInterceptor(new SqlStatementInterceptor()); 
            }); 
} 

No es tan complicado. Desde mi punto de vista, ciertamente es más fácil que tratar de obtener todo este XML impulsado a través de Fluent a NHibernate, ya que Fluent abstrae el archivo XML.

Tenga en cuenta que solo puede tener un solo interceptor, por lo que puede necesitar integrar esta función con su Interceptor existente, si ya tiene uno. En ese sentido, es posible que desee darle un nombre más amplio, por ejemplo, MyAppInterceptor, para no implicar un propósito específico, porque es posible que desee agregar otras funciones más adelante.

Espero que esto sea útil para otra persona! :-)

+0

Gran solución, simple como el infierno y simplemente funciona, se la agregó a mi prueba la fábrica de sesión, aunque es posible agregarla solo con #if DEBUG. ¡Gracias! –

+4

¿Quizás es posible completar los parámetros también? Obtengo '?' (Signos de interrogación) en lugar de valores en las consultas como 'SELECT * FROM MyObject WHERE Id =?'. Veo que hay un 'IEnumerable NHibernate.SqlCommand.SqlString.GetParameters()' –

+1

@Mike replace 'sql.ToString()' con 'base.OnPrepareStatement (sql)' –

33

Probablemente desee utilizar log4net, no ShowSql. Aquí está una cierta configuración para enviar consultas a la depuración:

<configSections> 
    <section name="log4net" 
    type="log4net.Config.Log4NetConfigurationSectionHandler,log4net" /> 
    </configSections> 

    <log4net debug="false"> 
    <appender name="WindowsDebugOutput" type="log4net.Appender.DebugAppender, 
     log4net"> 
     <layout type="log4net.Layout.PatternLayout,log4net"> 
     <param name="ConversionPattern" 
       value="%d{ABSOLUTE} %-5p %c{1}:%L - %m%n" /> 
     </layout> 
    </appender> 

    <logger name="NHibernate.SQL" additivity="false"> 
     <level value="DEBUG" /> 
     <appender-ref ref="WindowsDebugOutput" /> 
    </logger> 
    </log4net> 

y luego llamar a esto desde el código antes de la apertura de una sesión de NHibernate:

log4net.Config.XmlConfigurator.Configure(); 

Cuando se agrega una referencia a la DLL log4net, asegúrese de establecer su propiedad "Copiar local" a "verdadero".

Esto no es específico de FluentNHibernate, funciona igual en cualquier variante de NHibernate.

+0

Noobish pregunta, pero, ¿dónde poner este archivo de configuración en un proyecto de winforms?Muchos sitios web de documentación de Hibernate están caídos, y simplemente no puedo encontrar dónde colocar esta información XML. Gracias. –

+1

@Mike - debe ir a app.config en el directorio raíz del proyecto, que se copia al directorio bin como .exe.config en tiempo de compilación. –

+1

¡Excelente para tener respuesta en un comentario sobre una respuesta de más de 3 años! Muchas gracias! –

11

No he intentado esto con SQL Server, pero con SQLite, el siguiente código mostrará el SQL generado en la ventana Salida (menú Depurar -> Windows -> Salida, en VS2008).

El cuadro combinado "Mostrar salida desde:" en la ventana Salida debe establecerse en "Depurar" - VS2008 hizo eso automáticamente.

  sessionFactory = Fluently.Configure() 
       .Database(SQLiteConfiguration.Standard 
          .UsingFile(DbFile) 
          // Display generated SQL in Output window 
          .ShowSql() 
         ) 
       .Mappings(m => m.AutoMappings.Add(GetAutoPersistenceModel())) 
       .BuildSessionFactory() 
       ; 

Una palabra de advertencia: encender esto puede ralentizar considerablemente la ejecución.

+3

La ventana de salida en Visual Studio muestra la salida de Consola, Depuración y Rastreo. El método ShowSql escribe en la consola, no en Debug o Trace. Su recomendación no es diferente de lo que él ha dicho que ya está haciendo. –

+0

@Michael: ¡Acabo de volver a probar esto, y funciona EXACTAMENTE como se describe! ¿Posiblemente una diferencia en la implementación de la interfaz FNH con SQLite frente a SQL Server? –

+1

No es lo mismo "Depurar" (observe que no hay opción para "Rastreo" o "Consola"). :) Para ver si realmente está escribiendo en Debug, use algo como http://technet.microsoft.com/en-us/sysinternals/bb896647.aspx –

Cuestiones relacionadas