共用方式為


SqlContext 物件

適用於:SQL Server

當您呼叫程式或函式、在 Common Language Runtime (CLR) 使用者定義型別上呼叫方法,或當您的動作引發任何 .NET Framework 語言中定義的觸發程式時,請在伺服器中叫用 Managed 程式代碼。 由於執行此程式代碼是要求作為用戶連線的一部分,因此需要從伺服器中執行之程式代碼存取呼叫端的內容。 此外,只有在呼叫端的內容下執行時,特定數據存取作業才有效。 例如,存取觸發程式作業中使用的插入和刪除虛擬數據表,只有在呼叫端的內容下才有效。

呼叫者的內容會在 SqlContext 物件中抽象化。 如需詳細資訊,請參閱 Microsoft.SqlServer.Server.SqlContext

SqlContext 提供下列元件的存取權。

元件 描述
SqlPipe 此物件代表 管道 結果流向用戶端。 如需詳細資訊,請參閱SqlPipe 物件。
SqlTriggerContext 此物件只能從 CLR 觸發程式內擷取。 它提供導致觸發程式引發之作業的相關信息,以及已更新之數據行的對應。 如需詳細資訊,請參閱 SqlTriggerContext 物件
IsAvailable 這個屬性可用來判斷內容可用性。
WindowsIdentity 這個屬性是用來擷取呼叫端的 Windows 身分識別。

判斷內容可用性

藉由檢查 SqlContext 物件的 IsAvailable 屬性,查詢 SqlContext 類別,以查看目前執行的程式代碼是否正在進程中執行。 IsAvailable 屬性是唯讀的,如果呼叫程式代碼是在 SQL Server 內執行,而且如果可以存取其他 SqlContext 成員,則會傳回 True。 如果 IsAvailable 屬性傳回 False,則所有其他 SqlContext 成員都會擲回 InvalidOperationException,如果使用的話。 如果 IsAvailable 傳回 False,則任何嘗試開啟連接字串中有 “context connection=true” 的連接物件會失敗。

擷取 Windows 身分識別

在 SQL Server 內執行的 CLR 程式代碼一律會在行程帳戶的內容中叫用。 如果程式代碼應該使用呼叫使用者的身分識別來執行特定動作,而不是 SQL Server 進程識別,則應該透過 SqlContext 物件的 WindowsIdentity 屬性來取得模擬令牌。 WindowsIdentity 屬性會傳回 WindowsIdentity 實例,代表呼叫端的 Windows 身分識別,如果使用 SQL Server 驗證驗證用戶端,則傳回 null。 只有標示 EXTERNAL_ACCESSUNSAFE 許可權的元件才能存取此屬性。

取得 WindowsIdentity 對象之後,呼叫端可以模擬客戶端帳戶,並代表其執行動作。

只有當起始執行預存程式或函式的用戶端使用 Windows 驗證連線到伺服器時,才能透過 SqlContext.WindowsIdentity 來取得呼叫端的身分識別。 如果改用 SQL Server 驗證,則此屬性為 null,而且程式代碼無法模擬呼叫端。

範例

下列範例示範如何取得呼叫用戶端的 Windows 身分識別,並模擬用戶端。

[Microsoft.SqlServer.Server.SqlProcedure]
public static void WindowsIDTestProc()
{
    WindowsIdentity clientId = null;
    WindowsImpersonationContext impersonatedUser = null;

    // Get the client ID.
    clientId = SqlContext.WindowsIdentity;

    // This outer try block is used to thwart exception filter
    // attacks which would prevent the inner finally
    // block from executing and resetting the impersonation.
    try
    {
        try
        {
            impersonatedUser = clientId.Impersonate();
            if (impersonatedUser != null)
            {
                // Perform some action using impersonation.
            }
        }
        finally
        {
            // Undo impersonation.
            if (impersonatedUser != null)
                impersonatedUser.Undo();
        }
    }
    catch
    {
        throw;
    }
}