本文聚焦 SQL CLR 開發中的兩大關鍵環節:Visual Studio 整合除錯與生產環境手動部署,並總結實戰中遇到的典型錯誤與解決方案。
Application Debugging 與 Allow SQL/CLR Debugging 已勾選

前提:必須先建置並部署至目標 SQL Server。
Test Scripts → Test.sql (專案自動建立)Test.sql → Debug Script
Msg 10314: ... assembly may not be trusted with PERMISSION_SET = EXTERNAL_ACCESS or UNSAFE.
Msg 10327: CREATE ASSEMBLY failed because assembly is not authorized for PERMISSION_SET = EXTERNAL_ACCESS.
原因:當前登入帳戶無權存取外部資源,或資料庫 TRUSTWORTHY 未開啟,或擁有者非 sa。
解決:切換至 sa 帳戶執行:
USE TargetDB; GO
EXEC sp_changedbowner 'sa';
原因:使用 NT 帳戶連線,需明確模擬呼叫者身份。
正確模式:
public static void MyProc() {
WindowsIdentity id = SqlContext.WindowsIdentity;
WindowsImpersonationContext ctx = id.Impersonate();
try {
using (var conn = new SqlConnection("Server=Remote;Integrated Security=true")) {
conn.Open(); // 此處必須在 Undo 之前
// 執行工作...
}
} finally {
ctx.Undo(); // 必須執行!
}
// Undo 之後才能使用 SqlContext.Pipe 等
}
鐵律:Undo() 必須在 finally 區塊執行,且必須在使用 SqlContext 物件之前完成模擬與復原。
場景:宿主伺服器 A 需存取採 Windows 驗證的伺服器 B。
方案:在 A 建立 Linked Server 指向 B,查詢語法:
<LinkedServer>.<DBName>.<dbo.TableName>
無法直接用 SqlContext 或連線字串跨機存取,Linked Server 是正規解法。
*.XmlSerializers.dll適用於將開發環境組件部署至生產伺服器:
-- 1. 環境準備 (僅首次)
EXEC sp_configure 'clr enabled', 1; RECONFIGURE WITH OVERRIDE;
ALTER DATABASE TargetDB SET TRUSTWORTHY ON;
USE TargetDB; EXEC sp_changedbowner 'sa';
-- 2. 清理舊版本 (安全冪等)
IF OBJECT_ID('dbo.SyncHierarchy') IS NOT NULL BEGIN
PRINT 'Dropping procedure...'; DROP PROCEDURE dbo.SyncHierarchy; END
IF EXISTS (SELECT * FROM sys.assemblies WHERE name = 'SqlClrSharePointSynchronizerXML') BEGIN
PRINT 'Dropping XML assembly...'; DROP ASSEMBLY SqlClrSharePointSynchronizerXML WITH NO DEPENDENTS; END
IF EXISTS (SELECT * FROM sys.assemblies WHERE name = 'SqlClrSharePointSynchronizer') BEGIN
PRINT 'Dropping main assembly...'; DROP ASSEMBLY SqlClrSharePointSynchronizer WITH NO DEPENDENTS; END
GO
-- 3. 部署組件
DECLARE @path NVARCHAR(1000) = 'E:\Deploy\SqlClrSharePointSynchronizer\bin\Debug\';
PRINT 'Creating main assembly...';
EXEC ('CREATE ASSEMBLY [SqlClrSharePointSynchronizer] FROM ''' + @path + 'SqlClrSharePointSynchronizer.dll'' WITH PERMISSION_SET = EXTERNAL_ACCESS');
PRINT 'Creating XML assembly...';
EXEC ('CREATE ASSEMBLY [SqlClrSharePointSynchronizerXML] FROM ''' + @path + 'SqlClrSharePointSynchronizer.XmlSerializers.dll'' WITH PERMISSION_SET = EXTERNAL_ACCESS');
GO
-- 4. 建立預存程序
CREATE PROCEDURE [dbo].[SyncHierarchy]
@siteUrl NVARCHAR(4000), @linkServer NVARCHAR(4000)
WITH EXECUTE AS CALLER
AS EXTERNAL NAME [SqlClrSharePointSynchronizer].[Synchronizer].[SyncHierarchy];
GO
TRUSTWORTHY ON + sa owner + EXTERNAL_ACCESS + Impersonate/Undo 配對掌握這些,SQL CLR 從開發到上線不再是黑盒。