2008-09-12 8 views
12

ADO.NET을 사용하여 SQL Server 2005에 액세스하고 있으며 내가 호출하는 T-SQL 저장 프로 시저 내부에서 로그온 할 수 있기를 원합니다. 어떻게 든 가능합니까?T-SQL에 로그인하는 방법

ADO.NET을 사용할 때 'print'-statement의 결과를 볼 수 없으며 이상적인 솔루션을 디버깅하기위한 로깅을 사용하고자하므로 SysInternals에서 DebugView로 메시지를 보내야합니다.

+0

로그인 하시겠습니까? – Josef

+0

정보를 디버깅하는 것만으로 "X is Foo" –

답변

8

GO 당신에게 로그 데이터 사용을 저장하는 테이블을 생성합니다.어셈블리는 강력한 이름의 키 파일로 서명되어야합니다.

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

는 키와 로그인을 만든 :

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 

가 그럼 난 T-SQL 절차에 로그인 할 수 있었다

exec Debug @message = 'Hello World' 
를 사용하여 :

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 

는 SQL 서버로를 수입

5

새 행을 삽입하기 만하면 테이블에 로그온하거나 CLR 저장 프로 시저를 구현하여 파일에 쓸 수 있습니다.

조치가 트랜잭션에서 발생하고 트랜잭션이 롤백되면 로그 항목이 사라 지므로 테이블에 기록하는 데주의하십시오.

+3

로깅이 사라지는 문제를 방지하기 위해 로그 엔트리를 테이블 변수에 기록한 다음 트랜잭션이 커밋되거나 롤백 된 후 테이블 변수 데이터를 로그 테이블에 삽입합니다 . – HLGEM

5

SQL sproc 내부에서 로깅하는 것이 데이터베이스 자체를 더 잘 수행 할 수 있습니다. T-SQL은 파일에 쓸 수는 있지만 실제로 설계된 것은 아닙니다.

6

나는 로그 테이블에 글을 쓰는 것이 나의 취향이라고 생각한다.

또는 2005를 사용하는 경우 간단한 SQLCLR 프로 시저를 작성하여 EventLog를 랩핑 할 수 있습니다.

아니면 SQL 로그

2

PRINT 명령 거기에 기록하기를 원한다면 당신은 xp_logevent를 사용할 수 있지만 당신이 그것을 쿼리 할 수 ​​있도록 나는 테이블에 로그인 선호합니다.

0

메시지를 되돌리기 위해 출력 변수를 사용할 수 있지만 오류없이 실행중인 proc를 사용합니다.

create procedure usp_LoggableProc 

@log varchar(max) OUTPUT 

as 

-- T-SQL statement here ... 

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

그리고 somehwere 당신의 ADO 코드 :

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

당신은 당신이 필요로 해, 평소의 SQLException 오류를 통해 당신에게 사용할 수있는 정보와 사용자 정의 오류를 만들 RAISERROR를 사용할 수 있습니다 당신의 ADO 코드의 컬렉션 :

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

흠하지만, 그래, 그냥 오류로 VARCHAR 메시지를 삽입 단지 디버깅 및 상황에 기분이 도움이되지 수 다른 사람들과 같이 테이블은 당신이 디버깅 할 때 제안하고 * 선택합니다.

1

저장 프로 시저 내에서 로그 테이블에 행을 쓸 수 있습니다. 다른 사람들이 지적했듯이, CLR이나 xp_logevent를 사용하여 텍스트 파일이나 다른 로그에 쓸 수는 있지만, 그러한 용도로 사용하는 것보다 더 많은 볼륨이 필요합니다.

트랜잭션이 실패 할 때 까다로운 경우가 발생합니다 (로그가 필요합니다). 이러한 트랜잭션 중에 발생하는 모든 로깅은 트랜잭션의 일부로 롤백되므로 클라이언트가 오류를 로그하는 데 사용할 수있는 로깅 API를 갖는 것이 가장 좋습니다. 이것은 동일한 데이터베이스 또는 공유 데이터베이스에 기록하는 간단한 DAL 일 수 있습니다.

-1

- 다음 DDL의 SQL은 [DB] 내가 에릭 Z 수염 제안으로 SQLCLR-절차를 작성하여이 문제를 해결

/****** 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>  
*/ 
1

무엇 때문에 t의 가치는, 내가 발견 한 그 내도록 SqlConnection에 InfoMessage 핸들러를 지정하지 않는 경우 : 다음

MySqlConnectionInfoMessageHandler(object sender, SqlInfoMessageEventArgs e) 

다음 InfoMessageHandler의 서명은 다음과 같습니다

sqlConnection.InfoMessage += new SqlInfoMessageEventHandler(MySqlConnectionInfoMessageHandler); 

내 저장된 Procs 내 내 PRINT 문을 DbgView 나타나지 않습니다.

+0

이것은 많은 부분에있어서 가장 좋은 답입니다. – Contango

0

Log4TSQL을 확인하실 수 있습니다. SQL Server 2005 - 2008에서 저장 프로 시저 및 트리거에 대한 데이터베이스 로깅을 제공합니다. 프로 시저/트리거별로 별도의 독립적 인 로그 수준을 설정할 수 있습니다.

+0

뒤에 사용 된 아키텍처는 무엇입니까? 롤백 중 LOG4SQL이 로그 데이터를 저장하는 방법은 무엇입니까? –