@@ -346,5 +346,160 @@ public static void WriteTransactionRollbackError(this SqlDiagnosticListener @thi
346346 } ) ;
347347 }
348348 }
349+
350+ public static DiagnosticScope CreateCommandScope ( this SqlDiagnosticListener @this , SqlCommand command , SqlTransaction transaction , [ CallerMemberName ] string operationName = "" )
351+ {
352+ return DiagnosticScope . CreateCommandScope ( @this , command , transaction , operationName ) ;
353+ }
354+
355+ public static DiagnosticTransactionScope CreateTransactionCommitScope ( this SqlDiagnosticListener @this , IsolationLevel isolationLevel , SqlConnection connection , SqlInternalTransaction transaction , [ CallerMemberName ] string operationName = "" )
356+ {
357+ return DiagnosticTransactionScope . CreateTransactionCommitScope ( @this , isolationLevel , connection , transaction , operationName ) ;
358+ }
359+
360+ public static DiagnosticTransactionScope CreateTransactionRollbackScope ( this SqlDiagnosticListener @this , IsolationLevel isolationLevel , SqlConnection connection , SqlInternalTransaction transaction , string transactionName , [ CallerMemberName ] string operationName = "" )
361+ {
362+ return DiagnosticTransactionScope . CreateTransactionRollbackScope ( @this , isolationLevel , connection , transaction , transactionName , operationName ) ;
363+ }
364+ }
365+
366+ internal ref struct DiagnosticScope //: IDisposable //ref structs cannot implement interfaces but the compiler will use pattern matching
367+ {
368+ private const int CommandOperation = 1 ;
369+ private const int ConnectionOpenOperation = 2 ;
370+
371+ private readonly SqlDiagnosticListener _diagnostics ;
372+ private readonly int _operation ;
373+ private readonly string _operationName ;
374+ private readonly Guid _operationId ;
375+ private readonly object _context1 ;
376+ private readonly object _context2 ;
377+ private Exception _exception ;
378+
379+ private DiagnosticScope ( SqlDiagnosticListener diagnostics , int operation , Guid operationsId , string operationName , object context1 , object context2 )
380+ {
381+ _diagnostics = diagnostics ;
382+ _operation = operation ;
383+ _operationId = operationsId ;
384+ _operationName = operationName ;
385+ _context1 = context1 ;
386+ _context2 = context2 ;
387+ _exception = null ;
388+ }
389+
390+ public void Dispose ( )
391+ {
392+ switch ( _operation )
393+ {
394+ case CommandOperation :
395+ if ( _exception != null )
396+ {
397+ _diagnostics . WriteCommandError ( _operationId , ( SqlCommand ) _context1 , ( SqlTransaction ) _context2 , _exception , _operationName ) ;
398+ }
399+ else
400+ {
401+ _diagnostics . WriteCommandAfter ( _operationId , ( SqlCommand ) _context1 , ( SqlTransaction ) _context2 , _operationName ) ;
402+ }
403+ break ;
404+
405+ case ConnectionOpenOperation :
406+ if ( _exception != null )
407+ {
408+ _diagnostics . WriteConnectionOpenError ( _operationId , ( SqlConnection ) _context1 , _exception , _operationName ) ;
409+ }
410+ else
411+ {
412+ _diagnostics . WriteConnectionOpenAfter ( _operationId , ( SqlConnection ) _context1 , _operationName ) ;
413+ }
414+ break ;
415+
416+ // ConnectionCloseOperation is not implemented because it is conditionally emitted and that requires manual calls to the write apis
417+ }
418+ }
419+
420+ public void SetException ( Exception ex )
421+ {
422+ _exception = ex ;
423+ }
424+
425+ public static DiagnosticScope CreateCommandScope ( SqlDiagnosticListener diagnostics , SqlCommand command , SqlTransaction transaction , [ CallerMemberName ] string operationName = "" )
426+ {
427+ Guid operationId = diagnostics . WriteCommandBefore ( command , transaction , operationName ) ;
428+ return new DiagnosticScope ( diagnostics , CommandOperation , operationId , operationName , command , transaction ) ;
429+ }
430+ }
431+
432+ internal ref struct DiagnosticTransactionScope //: IDisposable //ref structs cannot implement interfaces but the compiler will use pattern matching
433+ {
434+ public const int TransactionCommit = 1 ;
435+ public const int TransactionRollback = 2 ;
436+
437+ private readonly SqlDiagnosticListener _diagnostics ;
438+ private readonly int _operation ;
439+ private readonly Guid _operationId ;
440+ private readonly string _operationName ;
441+ private readonly IsolationLevel _isolationLevel ;
442+ private readonly SqlConnection _connection ;
443+ private readonly SqlInternalTransaction _transaction ;
444+ private readonly string _transactionName ;
445+ private Exception _exception ;
446+
447+ public DiagnosticTransactionScope ( SqlDiagnosticListener diagnostics , int operation , Guid operationId , string operationName , IsolationLevel isolationLevel , SqlConnection connection , SqlInternalTransaction transaction , string transactionName )
448+ {
449+ _diagnostics = diagnostics ;
450+ _operation = operation ;
451+ _operationId = operationId ;
452+ _operationName = operationName ;
453+ _isolationLevel = isolationLevel ;
454+ _connection = connection ;
455+ _transaction = transaction ;
456+ _transactionName = transactionName ;
457+ _exception = null ;
458+ }
459+
460+ public void Dispose ( )
461+ {
462+ switch ( _operation )
463+ {
464+ case TransactionCommit :
465+ if ( _exception != null )
466+ {
467+ _diagnostics . WriteTransactionCommitError ( _operationId , _isolationLevel , _connection , _transaction , _exception , _operationName ) ;
468+ }
469+ else
470+ {
471+ _diagnostics . WriteTransactionCommitAfter ( _operationId , _isolationLevel , _connection , _transaction , _operationName ) ;
472+ }
473+ break ;
474+
475+ case TransactionRollback :
476+ if ( _exception != null )
477+ {
478+ _diagnostics . WriteTransactionRollbackError ( _operationId , _isolationLevel , _connection , _transaction , _exception , _transactionName , _operationName ) ;
479+ }
480+ else
481+ {
482+ _diagnostics . WriteTransactionRollbackAfter ( _operationId , _isolationLevel , _connection , _transaction , _transactionName , _operationName ) ;
483+ }
484+ break ;
485+ }
486+ }
487+
488+ public void SetException ( Exception ex )
489+ {
490+ _exception = ex ;
491+ }
492+
493+ public static DiagnosticTransactionScope CreateTransactionCommitScope ( SqlDiagnosticListener diagnostics , IsolationLevel isolationLevel , SqlConnection connection , SqlInternalTransaction transaction , [ CallerMemberName ] string operationName = "" )
494+ {
495+ Guid operationId = diagnostics . WriteTransactionCommitBefore ( isolationLevel , connection , transaction , operationName ) ;
496+ return new DiagnosticTransactionScope ( diagnostics , TransactionCommit , operationId , operationName , isolationLevel , connection , transaction , null ) ;
497+ }
498+
499+ public static DiagnosticTransactionScope CreateTransactionRollbackScope ( SqlDiagnosticListener diagnostics , IsolationLevel isolationLevel , SqlConnection connection , SqlInternalTransaction transaction , string transactionName , [ CallerMemberName ] string operationName = "" )
500+ {
501+ Guid operationId = diagnostics . WriteTransactionRollbackBefore ( isolationLevel , connection , transaction , transactionName , operationName ) ;
502+ return new DiagnosticTransactionScope ( diagnostics , TransactionCommit , operationId , operationName , isolationLevel , connection , transaction , transactionName ) ;
503+ }
349504 }
350505}
0 commit comments