更新:2007 年 11 月
這個主題適用於:
版本 |
Visual Basic |
C# |
C++ |
Web Developer |
|---|---|---|---|---|
Express 版 |
![]() |
![]() |
![]() |
![]() |
Standard 版 |
![]() |
![]() |
![]() |
![]() |
Pro/Team 版 |
![]() |
![]() |
![]() |
![]() |
表格圖例:
![]() |
套用 |
![]() |
不套用 |
![]() |
預設隱藏的命令。 |
本主題將包含示範偵錯多層應用程式的範例程式碼,以及描述從用戶端或多層應用程式中的應用程式碼,偵錯至 SQL Server 2005 內所執行的資料庫物件程式碼的必要步驟。
應用程式層和資料庫層之間的轉換需要在目標層設定中斷點;否則當您嘗試逐步執行至目標層時,程式碼將會繼續執行而不停止。但是在資料庫層中,T-SQL 和 SQL CLR 程式碼之間的轉換不需要中斷點來啟用在兩者間的逐步執行。
下列範例會使用 AdventureWorks 資料庫,並且在不同的層以及語言之間往前或往後逐步執行。範例的用意是用來說明這些轉換,而這顯然並不是真實的企業案例。
呼叫了三個預存程序:
DeleteCurrency 是使用指定貨幣代碼刪除貨幣的 SQL CLR 預存程序。
DeleteCurrency_T_SQL 執行相同的動作,但是是以 T-SQL 撰寫。
DeleteCurrencyDriver 會使用指定欲刪除貨幣代碼的輸入參數,來呼叫前面的兩個預存程序。
應用程式碼會呼叫三個預存程序,以傳遞貨幣代碼參數。這兩個「非驅動程式」預存程序會從兩個不同的內容呼叫:從 DeleteCurrencyDriver 以及直接從應用程式。在第一個內容中,您可以從 DeleteCurrencyDriver 逐步執行至另外兩個預存程序。從應用程式呼叫時,您就無法直接逐步執行至這兩個預存程序,必須在預存程序中設定中斷點。
偵錯資料庫應用程式
在新的 SQL Server 專案中,建立與 AdventureWorks 資料庫的連線。如需詳細資訊,請參閱 HOW TO:連接資料庫。
使用下列第一個範例區段中的程式碼建立 T-SQL 預存程序,並將其命名為 DeleteCurrency_T_SQL.。如需這項動作,或是這個程序中任何步驟的詳細資訊,請參閱 HOW TO:使用 SQL Server 專案類型開發。
使用下列第二個範例區段的程式碼建立 SQL CLR 預存程序,並將其命名為 DeleteCurrency.cs。
使用下列第三個範例區段的程式碼建立 SQL CLR 預存程序,並將其命名為 DeleteCurrencyDriver。
在 [偵錯] 功能表上按一下 [啟動],以便將這些變更編譯和部署至 AdventureWorks 資料庫。
在每個預存程序中設定至少一個中斷點。無法從機器碼或 Managed 程式碼逐步執行至預存程序。
在 Visual Studio 中建立新的主控台專案。
將第四個範例中的程式碼貼到文字編輯器中。
在每個預存程序的呼叫前後放置中斷點。
按 F5 執行應用程式。
逐步執行不同的模組。
嘗試移除某些中斷點,以檢視在不同層和語言之間嘗試逐步執行的效果。
若要完成偵錯,請從 Visual Studio [偵錯] 功能表清除所有中斷點,然後按 F5。
範例
本節包含 T-SQL 預存程序的程式碼。
CREATE PROCEDURE dbo.DeleteCurrency_T_SQL
(
@CurrencyCode nvarchar(3)
)
AS
SET NOCOUNT ON
DELETE Sales.Currency
WHERE CurrencyCode = @currencyCode
RETURN
這個程式碼包含從驅動程式預存程序呼叫之 SQL CLR 預存程序的程式碼。
using System;
using System.Data.SqlTypes;
using System.Data.SqlClient;
using Microsoft.SqlServer.Server;
public partial class StoredProcedures
{
[SqlProcedure]
public static void DeleteCurrency(SqlString currencyCode)
{
string sCmd = "DELETE Sales.Currency WHERE CurrencyCode = '" + currencyCode.Value + "'";
SqlConnection conn = new SqlConnection("Context Connection=True");
conn.Open();
SqlCommand DeleteCurrencyCommand = new SqlCommand( sCmd , conn);
DeleteCurrencyCommand.ExecuteNonQuery();
}
}
這個程式碼包含呼叫其他程序之 SQL CLR 驅動程式程序的程式碼。應用程式層會呼叫這個預存程序。
using System;
using System.Data;
using System.Data.SqlClient;
using System.Data.SqlTypes;
using Microsoft.SqlServer.Server;
public partial class StoredProcedures
{
[SqlProcedure]
public static void DeleteCurrencyDriver(SqlString CurrencyCode)
{
string sCommand = "DELETE Sales.Currency WHERE CurrencyCode = '" + CurrencyCode.Value + "'";
SqlConnection conn = new SqlConnection("Context Connection=True");
conn.Open();
SqlCommand DeleteCurrencyCommand = new SqlCommand(sCommand, conn);
DeleteCurrencyCommand.ExecuteNonQuery();
// Now execute a T-SQL stored procedure.
DeleteCurrencyCommand.CommandType = CommandType.StoredProcedure;
DeleteCurrencyCommand.CommandText = "DeleteCurrency_T_SQL";
// Fill the parameters collection based upon stored procedure.
SqlParameter workParam = null;
workParam = DeleteCurrencyCommand.Parameters.Add("@CurrencyCode", SqlDbType.NChar, 3);
DeleteCurrencyCommand.Parameters["@CurrencyCode"].Value = "ESC";
try { DeleteCurrencyCommand.ExecuteNonQuery(); }
catch { }
// Now execute a CLR stored procedure.
DeleteCurrencyCommand.CommandText = "DeleteCurrency";
try { DeleteCurrencyCommand.ExecuteNonQuery(); }
catch { }
}
};
這個程式碼包含呼叫驅動程式預存程序的應用程式碼,以及直接呼叫 T-SQL 和 SQL CLR 預存程序的應用程式碼。
using System;
using System.Data;
using System.Data.SqlClient;
using System.Data.SqlTypes;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder();
builder.DataSource = <server>;
builder.IntegratedSecurity = true;
builder.InitialCatalog = <database>;
SqlConnection SqlConnection1 = new SqlConnection(builder.ConnectionString);
SqlConnection1.Open();
SqlCommand procCommand = new SqlCommand();
procCommand.CommandText = "DeleteCurrencyDriver";
procCommand.CommandType = CommandType.StoredProcedure;
procCommand.Connection = SqlConnection1;
// Fill parameters collection for the stored procedure.
SqlParameter workParam = null;
workParam = procCommand.Parameters.Add("@CurrencyCode", SqlDbType.NChar, 3);
procCommand.Parameters["@CurrencyCode"].Value = "ESC";
try { procCommand.ExecuteNonQuery(); }
catch (SqlException e) { DumpException(e); }
procCommand.CommandText = "DeleteCurrency";
try { procCommand.ExecuteNonQuery(); }
catch (SqlException e) { DumpException(e); }
procCommand.CommandText = "DeleteCurrency_T_SQL";
try { procCommand.ExecuteNonQuery(); }
catch (SqlException e) { DumpException(e); }
SqlConnection1.Close();
}
static void DumpException(SqlException e)
{
string errorMessages = "";
for (int i = 0; i < e.Errors.Count; i++)
{
errorMessages += "Index #" + i + "\n" +
"Message: " + e.Errors[i].Message + "\n" +
"LineNumber: " + e.Errors[i].LineNumber + "\n" +
"Source: " + e.Errors[i].Source + "\n" +
"Procedure: " + e.Errors[i].Procedure + "\n";
}
System.Diagnostics.EventLog log = new System.Diagnostics.EventLog();
log.Source = "My Application";
log.WriteEntry(errorMessages);
Console.WriteLine("An exception occurred. Please contact your system administrator.");
}
}
}
.gif)
.gif)
.gif)