Pergunta

Eu estou usando ADO.NET para acessar o SQL Server 2005 e gostaria de ser capaz de fazer logon a partir de dentro da T-SQL procedimentos armazenados que eu estou chamando.É que, de alguma forma, possível?

Eu sou incapaz de ver a saída do 'imprimir'-declaração quando utilizar ADO.NET e já que eu quero usar o log apenas para depurando a solução ideal seria a de emitir mensagens para DebugView da SysInternals.

Foi útil?

Solução

Eu resolvi isso escrevendo um SQLCLR-procedimento Eric Z Barba sugerido.A montagem deve ser assinado com uma chave de nome forte arquivo.

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;
        }
    }
}

Criou uma chave e um nome de usuário:

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  

Importados para o 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

Então eu era capaz de entrar em T-SQL utilizando procedimentos

exec Debug @message = 'Hello World'

Outras dicas

Eu acho que escrever para uma tabela de log seria a minha preferência.

Em alternativa, se já estiver a utilizar 2005, você poderia escrever um simples SQLCLR procedimento para embrulhar em torno de registo de eventos.

Ou você pode usar xp_logevent se você quiser escrever para log SQL

Você pode registo a uma tabela, inserindo uma nova linha, ou você pode implementar um procedimento CLR armazenado para escrever para um ficheiro.

Tenha cuidado com a escrita para uma tabela, porque, se a ação acontece em uma transação e a transação, fica anulada, o seu registo de entrada irá desaparecer.

O registo de dentro de um SQL sproc seria melhor feito no próprio banco de dados.T-SQL pode gravar arquivos, mas não é realmente concebido para isso.

Há o IMPRIMIR de comando, mas eu prefiro fazer logon em uma tabela para que você possa consulta-lo.

Você pode escrever linhas a uma tabela de log de dentro de um procedimento armazenado.Como outros já indicado, você poderia sair de sua maneira de escrever algum texto ou ficheiro de registo com o CLR ou xp_logevent, mas parece que você precisa de mais volume do que seria prático para tais utilizações.

Os casos difíceis ocorrer (e é com estes que você realmente precisa de seu log) quando falha de transações.Uma vez que qualquer log que ocorre durante estas operações será revertida junto com a transação de que eles são parte de, é melhor ter uma API de log que os seus clientes podem usar o log de erros.Este pode ser um simples DAL que os logs para o mesmo banco de dados, ou para ser partilhado.

Por que vale a pena, eu achei que quando eu não atribuir um InfoMessage manipulador para o meu SqlConnection:

sqlConnection.InfoMessage += new SqlInfoMessageEventHandler(MySqlConnectionInfoMessageHandler);

onde a assinatura do InfoMessageHandler parecido com este:

MySqlConnectionInfoMessageHandler(object sender, SqlInfoMessageEventArgs e)

então a minha IMPRESSÃO instruções na minha Procedimentos Armazenados não aparecem na DbgView.

Você pode usar variáveis de saída para passar de volta as mensagens, mas que depende do processo de execução sem erros.

create procedure usp_LoggableProc 

@log varchar(max) OUTPUT 

as

-- T-SQL statement here ...

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

E, em seguida, em seu código ADO algures:

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

Você pode usar raiserror para criar os seus próprios erros personalizados com as informações que você precisar e que estará disponível para você através do usual SqlException colecção de Erros no seu código ADO:

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

Hmmm, mas sim, não pode deixar de sentir apenas para depuração e na sua situação, basta inserir varchar mensagens para uma tabela de erro, como os outros têm sugerido e seleccione: * quando você está depurando.

Você pode querer verificar para Log4TSQL.Ele fornece a base de Dados de Registo para Procedimentos Armazenados e Gatilhos no SQL Server 2005 - 2008.Você tem a possibilidade de configurar separada, independente de log-níveis por Procedimento/Disparador de base.

-- Os seguintes DDL sql irá criar a tabela para armazenar os dados de log USE [db] IR

/****** 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>      
*/  
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top