Question

J'utilise ADO.NET pour accéder à SQL Server 2005 et j'aimerais pouvoir me connecter depuis les procédures stockées T-SQL que j'appelle.Est-ce possible d’une manière ou d’une autre ?

Je ne parviens pas à voir le résultat de l'instruction 'print' lors de l'utilisation d'ADO.NET et comme je souhaite utiliser la journalisation uniquement pour le débogage, la solution idéale serait d'émettre des messages à DebugView à partir de SysInternals.

Était-ce utile?

La solution

J'ai résolu ce problème en écrivant une procédure SQLCLR comme l'a suggéré Eric Z Beard.L’assembly doit être signé avec un fichier de clé de nom fort.

using System;
using System.Data;
using System.Data.SqlClient;
using System.Data.SqlTypes;
using Microsoft.SqlServer.Server;

public partial class StoredProcedures
{
    [Microsoft.SqlServer.Server.SqlProcedure]
    public static int Debug(string s)
    {
        System.Diagnostics.Debug.WriteLine(s);
            return 0;
        }
    }
}

Création d'une clé et d'un login :

USE [master]
CREATE ASYMMETRIC KEY DebugProcKey FROM EXECUTABLE FILE =
'C:\..\SqlServerProject1\bin\Debug\SqlServerProject1.dll'

CREATE LOGIN DebugProcLogin FROM ASYMMETRIC KEY DebugProcKey 

GRANT UNSAFE ASSEMBLY TO DebugProcLogin  

Je l'ai importé dans SQL Server :

USE [mydb]
CREATE ASSEMBLY SqlServerProject1 FROM
'C:\..\SqlServerProject1\bin\Debug\SqlServerProject1.dll' 
WITH PERMISSION_SET = unsafe

CREATE FUNCTION dbo.Debug( @message as nvarchar(200) )
RETURNS int
AS EXTERNAL NAME SqlServerProject1.[StoredProcedures].Debug

Ensuite, j'ai pu me connecter aux procédures T-SQL en utilisant

exec Debug @message = 'Hello World'

Autres conseils

Je pense qu'écrire dans une table de journal serait ma préférence.

Alternativement, comme vous utilisez 2005, vous pouvez écrire une simple procédure SQLCLR pour envelopper le journal des événements.

Ou vous pourriez utiliser xp_logevent si vous vouliez écrire dans le journal SQL

Vous pouvez soit vous connecter à une table en insérant simplement une nouvelle ligne, soit implémenter une procédure stockée CLR pour écrire dans un fichier.

Soyez prudent lorsque vous écrivez dans une table, car si l'action se produit dans une transaction et que la transaction est annulée, votre entrée de journal disparaîtra.

La journalisation depuis l'intérieur d'une procédure SQL serait mieux effectuée dans la base de données elle-même.T-SQL peut écrire dans des fichiers mais il n'est pas vraiment conçu pour cela.

Il y a le IMPRIMER commande, mais je préfère me connecter à une table pour que vous puissiez l'interroger.

Vous pouvez écrire des lignes dans une table de journal à partir d'une procédure stockée.Comme d'autres l'ont indiqué, vous pouvez faire tout votre possible pour écrire dans un fichier texte ou un autre journal avec CLR ou xp_logevent, mais il semble que vous ayez besoin de plus de volume que ce qui serait pratique pour de telles utilisations.

Les cas difficiles se produisent (et c'est pour ceux-là que vous avez vraiment besoin de votre journal) lorsque les transactions échouent.Étant donné que toute journalisation effectuée au cours de ces transactions sera annulée avec la transaction dont elles font partie, il est préférable de disposer d'une API de journalisation que vos clients peuvent utiliser pour consigner les erreurs.Il peut s'agir d'un simple DAL qui se connecte soit à la même base de données, soit à une base de données partagée.

Pour ce que ça vaut, j'ai constaté que lorsque je n'attribue pas de gestionnaire InfoMessage à mon SqlConnection :

sqlConnection.InfoMessage += new SqlInfoMessageEventHandler(MySqlConnectionInfoMessageHandler);

où la signature de l'InfoMessageHandler ressemble à ceci :

MySqlConnectionInfoMessageHandler(object sender, SqlInfoMessageEventArgs e)

alors mes instructions PRINT dans mes Procs stockés n'apparaissent pas dans DbgView.

Vous pouvez utiliser des variables de sortie pour renvoyer des messages, mais cela dépend de l'exécution du processus sans erreur.

create procedure usp_LoggableProc 

@log varchar(max) OUTPUT 

as

-- T-SQL statement here ...

select @log = @log + 'X is foo'

Et puis dans votre code ADO quelque part :

string log = (string)SqlCommand.Parameters["@log"].Value;

Vous pouvez utiliser raiserror pour créer vos propres erreurs personnalisées avec les informations dont vous avez besoin et qui seront disponibles via la collection habituelle d'erreurs SqlException dans votre code ADO :

RAISERROR('X is Foo', 10, 1)

Hmmm mais oui, je ne peux m'empêcher de penser uniquement au débogage et dans votre situation, insérez simplement des messages varchar dans une table d'erreurs comme les autres l'ont suggéré et sélectionnez * à partir de celle-ci lorsque vous déboguez.

Vous voudrez peut-être vérifier Log4TSQL.Il fournit une journalisation de base de données pour les procédures stockées et les déclencheurs dans SQL Server 2005 - 2008.Vous avez la possibilité de définir des niveaux de journalisation séparés et indépendants pour chaque procédure/déclencheur.

- Le DDL SQL suivant vous créera le tableau pour stocker les données de journal Utiliser [DB] GO

/****** Object:  Table [dbo].[tbData_Debug]    Script Date: 02/12/2009 22:30:03 ******/
SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

SET ANSI_PADDING ON
GO

CREATE TABLE [dbo].[tbData_Debug](
    [colTimeStamp] [timestamp] NULL,
    [colNiceTime] [varchar](200) NULL,
    [colDomain_User] [varchar](200) NULL,
    [colMsg] [varchar](4000) NULL,
    [colDebugLevel] [int] NULL,
    [colDebugMsg] [varchar](4000) NULL,
    [colPageName] [varchar](200) NULL,
    [colClassName] [varchar](200) NULL,
    [colMethodName] [varchar](200) NULL,
    [colMethodNameGui] [varchar](4000) NULL,
    [colRet] [int] NULL,
    [colLineNumber] [int] NULL,
    [colLineNumberGui] [int] NULL,
    [colProcedureName] [varchar](200) NULL,
    [colProcedureStep] [varchar](4000) NULL
) ON [PRIMARY]

GO

SET ANSI_PADDING OFF
GO




-- This stored procedure does write to the log table

USE [db]
GO
/****** Object:  StoredProcedure [dbo].[procUtils_AppDebug]    Script Date: 02/12/2009 22:29:24 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

ALTER PROCEDURE [dbo].[procUtils_AppDebug] (                  

@ret int = null OUT,     
@msgIn varchar(4000) = null ,   -- the msg which the user has seen   
@msgOut varchar(4000) = null OUT ,   -- the msg which the user has seen   
@domain_user varchar(200) = null ,                 -- the domain user echoing the message  
@debugMsgIn varchar(4000) = null  ,   -- the debug msg for internal use  
@debugMsgOut varchar(4000) = null  OUT,   -- the debug msg for internal use  
@pageName varchar(200) = null ,   -- the pageName originator of error  
@className varchar(200) = null ,   -- the class Name orinator of error  
@methodName varchar(200) = null ,   -- the methodName where the last error occured  
@methodNameGui varchar(4000) = null ,   -- the methodNameOfTheGui where the last error occured  
@lineNumber int = null ,  -- the line number of the line issueing the error  
@lineNumberGui int = null,   -- the line number of the line issueing the error               
@procedureName varchar(200) = null , -- the procedureName currently envoked
@procedureStep varchar(4000)  = null -- the steps of the procedure concatenated
)    

AS                  
BEGIN -- proc start                
 SET NOCOUNT ON;                

BEGIN TRY        --begin try      

declare @debugLevel int     
select @debugLevel =  Debug_Level from User_tb where Domain_Name = @domain_user  

/*                  
select * from tbData_Debug    order by 1 desc              
delete from tbData_Debug              
*/    


insert into tbData_Debug ( colNiceTime , colDomain_User , colMsg , colDebugLevel ,   
colDebugMsg , colPageName , colClassName , colMethodName , colMethodNameGui ,   
colRet , colLineNumber , colLineNumberGui , colProcedureName , colProcedureStep) values (
 dbo.funcGetNiceTime() , @domain_user  , @msgIn , @debugLevel ,@debugMsgIn , 
 @pageName , @className , @methodName  ,@MethodNameGui , @ret , 
 @lineNumber , @lineNumberGui , @procedureName , @procedureStep)     

set @debugMsgOut = @debugMsgIn  
set @msgOut = 'Action Registered'  
set @ret = @@ERROR     
return @ret                



END TRY        --end try      

BEGIN CATCH            
 PRINT 'In CATCH block.             
 Error number: ' + CAST(ERROR_NUMBER() AS varchar(10)) + '            
 Error message: ' + ERROR_MESSAGE() + '            
 Error severity: ' + CAST(ERROR_SEVERITY() AS varchar(10)) + '            
 Error state: ' + CAST(ERROR_STATE() AS varchar(10)) + '            
 XACT_STATE: ' + CAST(XACT_STATE() AS varchar(10));            

 set  @debugMsgOut = 'error at [procUtils_AppDebug]--- Error number: ' + CAST(ERROR_NUMBER() AS varchar(10)) + 'Error message: ' + ERROR_MESSAGE() + 'Error severity: ' +   
CAST(ERROR_SEVERITY() AS varchar(10)) + 'Error state: ' + CAST(ERROR_STATE() AS varchar(10)) + 'XACT_STATE: ' + CAST(XACT_STATE() AS varchar(10))            
set @msgIn= 'error while saving application error info into database'  
insert into tbData_Debug ( colMsg ) values ( @msgIn )     

set @debugMsgOut = @debugMsgIn +  @debugMsgOut  
set @msgOut = 'Action Registration failed'  
set @ret = 1           

END CATCH            


return  @ret                       
END --procedure end                 

/*       
<procedureDocumentation>      

<procedurename>procUtils_AppDebug<procedurename>      
<procedureDescription> Records events from the Application Layer </procedureDescription>    
<created>20090121</created>      
<createdby>Yordan Georgiev</createdby>      
<change>      

<changewhen><changewhen>      
<changeDescription></changeDescription>      
<changedBy></changedBy>      
</change>      


<testUsage>    

USE [db]    
GO    

DECLARE @return_value int,    
  @ret int,    
  @msgIn varchar(max),    
  @debugmsg varchar(4000)    

SELECT @ret = 1    
SELECT @msgIn = N'msg'    
SELECT @debugmsg = N'before'    

EXEC @return_value = [dbo].[procUtils_AppDebug]    
  @ret = @ret OUTPUT,    
  @msgIn = @msgIn OUTPUT,    
  @domain_user = N'domain_user',    
  @debugmsg = @debugmsg OUTPUT,    

  @methodName = N'methodName'    

SELECT @ret as N'@ret',    
  @msgIn as N'@msgIn',    
  @debugmsg as N'@debugmsg'    

SELECT 'Return Value' = @return_value    
select * from tbData_Debug order by 1 desc    
GO    

</testUsage>      
</procedureDocumentation>      
*/  
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top