다음을 통해 공유


헬로 월드 준비 샘플

Hello World Ready 샘플은 간단한 세계 준비 CLR(공용 언어 런타임) 통합 기반 저장 프로시저를 만들고, 배포하고, 테스트하는 데 관련된 기본 작업을 보여 줍니다. 전 세계에 준비된 구성 요소는 구성 요소의 소스 코드를 변경하지 않고도 전 세계 여러 시장에 대해 다양한 언어로 쉽게 지역화할 수 있습니다. 또한 이 샘플에서는 저장 프로시저에 의해 동적으로 생성되고 클라이언트로 반환되는 출력 매개 변수 및 레코드를 통해 데이터를 반환하는 방법을 보여 줍니다. 이 샘플은 이 애플리케이션을 지역화하는 것이 훨씬 쉽고 안전하다는 점을 제외하고 Hello World 샘플과 거의 동일합니다. 지역화된 텍스트를 변경하려면 다음이 필요합니다.

  1. 리소스 디렉터리의 특정 문화권에 대한 XML 파일(.resx 파일) 변경

  2. 를 사용하여 문화권의 리소스 파일 빌드 resgen

  3. 해당 문화권에 대해 업데이트된 위성 DLL 빌드

  4. SQL Server에서 해당 어셈블리 삭제 및 추가

CLR 저장 프로시저 자체의 소스 코드와 어셈블리는 변경되지 않습니다. build.cmd 리소스 어셈블리를 컴파일하고 연결하는 방법을 보여 주는 스크립트가 제공됩니다. 애플리케이션의 소스 코드는 현재 실행 중인 어셈블리를 기반으로 리소스 관리자를 만들지만 저장 프로시저가 포함된 문화권 중립 리소스를 DLL에 포함할 필요는 없습니다. 문화 System.Resources.NeutralResourcesLanguage attribute 권 중립 리소스가 위성 DLL에 존재할 수 있도록 허용합니다. 지역화된 텍스트를 추가하거나 변경해야 하는 경우 CLR 저장 프로시저가 포함된 기본 DLL을 변경할 필요가 없도록 이 목적을 위해 별도의 DLL을 사용하는 것이 훨씬 낫습니다. 이는 형식을 삭제하고 다시 추가하기 어렵게 만드는 열 및 기타 종속성이 있을 수 있는 CLR 사용자 정의 형식에 특히 유용합니다. 일반적으로 위성 DLL 버전은 주 어셈블리 버전과 동일해야 합니다. 그러나 위성 어셈블리를 SatelliteContractVersion 업데이트하지 않고도 주 어셈블리를 업데이트할 수 있도록 특성을 사용할 수 있습니다. 자세한 내용은 Microsoft .NET 설명서의 클래스를 참조 ResourceManager 하세요.

필수 조건

이 샘플은 SQL Server 2005 이상 버전에서만 작동합니다.

이 프로젝트를 만들고 실행하려면 다음 소프트웨어를 설치해야 합니다.

  • SQL Server 또는 SQL Server Express. SQL Server Express 설명서 및 샘플 웹 사이트에서 SQL Server Express를 무료로 받을 수 있습니다.

  • SQL Server 개발자 웹 사이트에서 사용할 수 있는 AdventureWorks 데이터베이스

  • .NET Framework SDK 2.0 이상 또는 Microsoft Visual Studio 2005 이상. .NET Framework SDK를 무료로 얻을 수 있습니다.

  • 또한 다음 조건을 충족해야 합니다.

  • 사용 중인 SQL Server 인스턴스는 CLR 통합을 사용하도록 설정해야 합니다.

  • CLR 통합을 사용하도록 설정하려면 다음 단계를 수행합니다.

    CLR 통합 활성화

    • 다음 Transact-SQL 명령을 실행합니다.

    sp_configure 'clr enabled', 1

    GO

    RECONFIGURE

    GO

    비고

    CLR을 사용하도록 설정하려면 서버 수준 권한이 있어야 합니다ALTER SETTINGS. 이 권한은 서버 역할 및 sysadmin 고정 서버 역할의 serveradmin 멤버가 암시적으로 보유합니다.

  • AdventureWorks 데이터베이스는 사용 중인 SQL Server 인스턴스에 설치해야 합니다.

  • 사용 중인 SQL Server 인스턴스의 관리자가 아닌 경우 설치를 완료하려면 관리자에게 CreateAssembly 권한을 부여해야 합니다.

샘플 빌드

다음 지침을 사용하여 샘플을 만들고 실행합니다.

  1. Visual Studio 또는 .NET Framework 명령 프롬프트를 엽니다.

  2. 필요한 경우 샘플에 대한 디렉터리를 만듭니다. 이 예제에서는 C:\MySample을 사용합니다.

  3. c:\MySample에서 (Visual Basic 샘플용) 또는 HelloWorld.vb (C# 샘플의 경우) 만들고 HelloWorld.cs 적절한 Visual Basic 또는 C# 샘플 코드(아래)를 파일에 복사합니다.

  4. c:\MySample에서 파일을 messages.resx 만들고 샘플 코드를 파일에 복사합니다.

  5. c:\MySample에서 줄을 messages.de.resx 변경한 후와 같이 messages.de.resx 파일을 저장하여 파일을 messages.resx 만듭니다.

    • <value xml:space="preserve">Hello, World!</value>

    • 읽으려면

    • <value xml:space="preserve">Hallo Welt!</value>

  6. c:\MySample에서 줄을 messages.es.resx 변경한 후와 같이 messages.es.resx 파일을 저장하여 파일을 messages.resx 만듭니다.

    • <value xml:space="preserve">Hello, World!</value>

    • 읽으려면

    • <value xml:space="preserve">Hola a todos</value>

  7. c:\MySample에서 줄을 messages.fr.resx 변경한 후와 같이 messages.fr.resx 파일을 저장하여 파일을 messages.resx 만듭니다.

    • <value xml:space="preserve">Hello, World!</value>

    • 읽으려면

    • <value xml:space="preserve">Bonjour !</value>

  8. c:\MySample에서 줄을 messages.fr-FR.resx 변경한 후와 같이 messages.fr-FR.resx 파일을 저장하여 파일을 messages.resx 만듭니다.

    • <value xml:space="preserve">Hello, World!</value>

    • 읽으려면

    • <value xml:space="preserve">Bonjour de France!</value>

  9. c:\MySample에서 줄을 messages.it.resx 변경한 후와 같이 messages.it.resx 파일을 저장하여 파일을 messages.resx 만듭니다.

    • <value xml:space="preserve">Hello, World!</value>

    • 읽으려면

    • <value xml:space="preserve">Buongiorno</value>

  10. c:\MySample에서 줄을 messages.ja.resx 변경한 후와 같이 messages.ja.resx 파일을 저장하여 파일을 messages.resx 만듭니다.

    • <value xml:space="preserve">Hello, World!</value>

    • 읽으려면

    • <value xml:space="preserve"> ã"ã‚"にちは</value>

  11. c:\MySample에서 파일을 build.com 만들고 샘플 코드를 파일에 복사합니다.

  12. 명령 프롬프트에서 파일 빌드를 실행하여 위성 어셈블리를 빌드합니다.

  13. 다음 중 하나를 실행하여 명령줄 프롬프트에서 샘플 코드를 컴파일합니다.

    • Vbc /reference:C:\Windows\Microsoft.NET\Framework\v2.0.50727\System.Data.dll,C:\Windows\Microsoft.NET\Framework\v2.0.50727\System.dll,C:\Windows\Microsoft.NET\Framework\v2.0.50727\System.Xml.dll /out:HelloWorldReady.dll /target:library HelloWorld.vb

    • Csc /reference:C:\Windows\Microsoft.NET\Framework\v2.0.50727\System.Data.dll /reference:C:\Windows\Microsoft.NET\Framework\v2.0.50727\System.dll /reference:C:\Windows\Microsoft.NET\Framework\v2.0.50727\System.XML.dll /out:HelloWorldReady.dll /target:library Hello.csCopy the tsql installation code into a file and save it as Install.sql in the sample directory.

  14. 샘플이 다른 C:\MySample\디렉터리에 설치된 경우 해당 위치를 가리키도록 표시된 대로 파일을 Install.sql 편집합니다.

  15. 실행하여 어셈블리 및 저장 프로시저 배포

    • sqlcmd -E -I -i install.sql
  16. Transact-SQL 테스트 명령 스크립트를 파일에 복사하고 샘플 디렉터리에 저장 test.sql 합니다.

  17. 다음 명령을 사용하여 테스트 스크립트 실행

    • sqlcmd -E -I -i test.sql
  18. Transact-SQL 정리 스크립트를 파일에 복사하고 샘플 디렉터리에 저장 cleanup.sql 합니다.

  19. 다음 명령을 사용하여 스크립트 실행

    • sqlcmd -E -I -i cleanup.sql

예제 코드

다음은 이 샘플의 코드 목록입니다.

C# (프로그래밍 언어)

using System;  
using System.Data;  
using System.Data.Sql;  
using System.Data.SqlTypes;  
using Microsoft.SqlServer.Server;  
using System.Globalization;  
using System.Threading;  
using System.Resources;  
using System.Reflection;  
using System.Runtime.CompilerServices;  
  
[assembly: System.Resources.NeutralResourcesLanguage("", System.Resources.UltimateResourceFallbackLocation.Satellite)]  
[assembly: System.Security.Permissions.SecurityPermissionAttribute(System.Security.Permissions.SecurityAction.RequestMinimum)]  
[assembly: System.Runtime.ConstrainedExecution.ReliabilityContract(System.Runtime.ConstrainedExecution.Consistency.MayCorruptInstance, System.Runtime.ConstrainedExecution.Cer.None)]  
  
    public sealed partial class StoredProcedures  
    {  
        private StoredProcedures()  
        {  
        }  
  
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1021:AvoidOutParameters"), Microsoft.SqlServer.Server.SqlProcedure]  
        public static void HelloWorldReady(string culture, out string greeting)  
        {  
ResourceManager rm   
= new ResourceManager("Messages",   
Assembly.GetExecutingAssembly());  
  
string message = rm.GetString("HelloWorld", CultureInfo.GetCultureInfo(culture));  
  
            Microsoft.SqlServer.Server.SqlMetaData columnInfo  
                = new Microsoft.SqlServer.Server.SqlMetaData("Column1", SqlDbType.NVarChar, 24);  
            SqlDataRecord greetingRecord  
                = new SqlDataRecord(new Microsoft.SqlServer.Server.SqlMetaData[] { columnInfo });  
            greetingRecord.SetString(0, message);  
            SqlContext.Pipe.Send(greetingRecord);  
            greeting = message;  
        }  
    }  
  

Visual Basic (비주얼 베이직 언어)

Imports System  
Imports System.Data  
Imports System.Data.Sql  
Imports System.Data.SqlTypes  
Imports Microsoft.SqlServer.Server  
Imports System.Globalization  
Imports System.Resources  
Imports System.Reflection  
Imports System.Runtime.InteropServices  
<Assembly: AssemblyVersion("1.0.*")>   
<Assembly: System.Runtime.InteropServices.ComVisible(False)>   
<Assembly: System.CLSCompliant(True)>   
<Assembly: System.Resources.NeutralResourcesLanguage("", System.Resources.UltimateResourceFallbackLocation.Satellite)>   
<Assembly: System.Security.Permissions.SecurityPermissionAttribute(System.Security.Permissions.SecurityAction.RequestMinimum)>   
<Assembly: System.Runtime.ConstrainedExecution.ReliabilityContract(System.Runtime.ConstrainedExecution.Consistency.WillNotCorruptState, Runtime.ConstrainedExecution.Cer.None)>   
  
Partial Public NotInheritable Class StoredProcedures  
    Private Sub New()  
    End Sub  
    <Microsoft.SqlServer.Server.SqlProcedure()> _  
    Public Shared Sub HelloWorldReady(ByVal culture As String, ByRef greeting As String)  
        Dim rm As New ResourceManager("Messages", Assembly.GetExecutingAssembly())  
        Dim message As String = rm.GetString("HelloWorld", CultureInfo.GetCultureInfo(culture))  
        Dim columnInfo As New Microsoft.SqlServer.Server.SqlMetaData("Column1", _  
            SqlDbType.NVarChar, 24)  
        Dim greetingRecord As New SqlDataRecord(New  _  
            Microsoft.SqlServer.Server.SqlMetaData() {columnInfo})  
        greetingRecord.SetString(0, message)  
        SqlContext.Pipe.Send(greetingRecord)  
        greeting = message  
    End Sub  
End Class  
  

위성 build.com어셈블리를 빌드하는 것입니다.

resgen Messages.resx  
resgen Messages.de.resx  
resgen Messages.es.resx  
resgen Messages.fr.resx  
resgen Messages.fr-Fr.resx  
resgen Messages.it.resx  
resgen Messages.ja.resx  
if not exist de/ mkdir de  
if not exist es/ mkdir es  
if not exist fr/ mkdir fr  
if not exist fr-FR/ mkdir fr-FR  
if not exist it/ mkdir it  
if not exist ja/ mkdir ja  
al /t:lib /culture:de /embed:Messages.de.resources /out:de\HelloWorldReady.resources.dll  
al /t:lib /culture:es /embed:Messages.es.resources /out:es\HelloWorldReady.resources.dll  
al /t:lib /culture:fr /embed:Messages.fr.resources /out:fr\HelloWorldReady.resources.dll  
al /t:lib /culture:fr-FR /embed:Messages.fr-FR.resources /out:fr-FR\HelloWorldReady.resources.dll  
al /t:lib /culture:it /embed:Messages.it.resources /out:it\HelloWorldReady.resources.dll  
al /t:lib /culture:ja /embed:Messages.ja.resources /out:ja\HelloWorldReady.resources.dll  
al /t:lib /culture:"" /embed:Messages.resources /out:HelloWorldReady.resources.dll  

어셈블리를 배포하고 데이터베이스 내에 저장 프로시저를 만드는 Transact-SQL 설치 스크립트(Install.sql)입니다.

USE AdventureWorks  
GO  
  
-- Drop existing sproc and assembly if any.  
  
IF EXISTS (SELECT * FROM sys.procedures WHERE [name] = 'usp_HelloWorldReady')  
DROP PROCEDURE usp_HelloWorldReady;  
GO  
  
IF EXISTS (SELECT * FROM sys.assemblies WHERE [name] = 'HelloWorldReady')  
DROP ASSEMBLY HelloWorldReady;  
GO  
  
IF EXISTS (SELECT * FROM sys.assemblies WHERE [name] = 'HelloWorldReady.resources.neutral')  
DROP ASSEMBLY [HelloWorldReady.resources.neutral]  
GO  
  
IF EXISTS (SELECT * FROM sys.assemblies WHERE [name] = 'HelloWorldReady.resources.de')  
DROP ASSEMBLY [HelloWorldReady.resources.de]  
GO  
  
IF EXISTS (SELECT * FROM sys.assemblies WHERE [name] = 'HelloWorldReady.resources.es')  
DROP ASSEMBLY [HelloWorldReady.resources.es]  
GO  
  
IF EXISTS (SELECT * FROM sys.assemblies WHERE [name] = 'HelloWorldReady.resources.fr')  
DROP ASSEMBLY [HelloWorldReady.resources.fr]  
GO  
  
IF EXISTS (SELECT * FROM sys.assemblies WHERE [name] = 'HelloWorldReady.resources.fr-FR')  
DROP ASSEMBLY [HelloWorldReady.resources.fr-FR]  
GO  
  
IF EXISTS (SELECT * FROM sys.assemblies WHERE [name] = 'HelloWorldReady.resources.it')  
DROP ASSEMBLY [HelloWorldReady.resources.it]  
GO  
  
IF EXISTS (SELECT * FROM sys.assemblies WHERE [name] = 'HelloWorldReady.resources.ja')  
DROP ASSEMBLY [HelloWorldReady.resources.ja]  
GO  
  
DECLARE @SamplesPath nvarchar(1024)  
-- You may need to modify the value of this variable if you have installed the sample someplace other than the default location.  
Set @SamplesPath = N'C:\MySample\'  
  
-- Add the assembly and CLR integration based stored procedure  
  
CREATE ASSEMBLY HelloWorldReady  
FROM @SamplesPath + 'HelloWorldReady.dll'  
WITH permission_set = Safe;  
  
CREATE ASSEMBLY [HelloWorldReady.resources.neutral]  
FROM @SamplesPath + 'HelloWorldReady.resources.dll'  
WITH permission_set = Safe;   
  
CREATE ASSEMBLY [HelloWorldReady.resources.de]  
FROM @SamplesPath + '\de\HelloWorldReady.resources.dll'  
WITH permission_set = Safe;  
  
CREATE ASSEMBLY [HelloWorldReady.resources.es]  
FROM @SamplesPath + '\es\HelloWorldReady.resources.dll'  
WITH permission_set = Safe;  
  
CREATE ASSEMBLY [HelloWorldReady.resources.fr]  
FROM @SamplesPath + '\fr\HelloWorldReady.resources.dll'  
WITH permission_set = Safe;  
  
CREATE ASSEMBLY [HelloWorldReady.resources.fr-FR]  
FROM @SamplesPath + '\fr-FR\HelloWorldReady.resources.dll'  
WITH permission_set = Safe;  
  
CREATE ASSEMBLY [HelloWorldReady.resources.it]  
FROM @SamplesPath + '\it\HelloWorldReady.resources.dll'  
WITH permission_set = Safe;  
  
CREATE ASSEMBLY [HelloWorldReady.resources.ja]  
FROM @SamplesPath + '\ja\HelloWorldReady.resources.dll'  
WITH permission_set = Safe;  
GO  
  
CREATE PROCEDURE usp_HelloWorldReady  
(  
@Culture NVarchar(12),  
@Greeting NVarchar(24) OUTPUT  
)  
AS EXTERNAL NAME HelloWorldReady.StoredProcedures.HelloWorldReady;  
GO  
  
USE master;  
GO  

이는 test.sql각 로캘에서 함수를 실행하여 샘플을 테스트하는 것입니다.

USE AdventureWorks  
GO  
  
DECLARE @GreetingDe nvarchar(24);  
DECLARE @GreetingDe_CH nvarchar(24);  
DECLARE @GreetingEn nvarchar(24);  
DECLARE @GreetingEs nvarchar(24);  
DECLARE @GreetingFr nvarchar(24);  
DECLARE @GreetingFr_FR nvarchar(24);  
DECLARE @GreetingIt nvarchar(24);  
DECLARE @GreetingJa nvarchar(24);  
  
--German as spoken anywhere in the world (the neutral German culture)  
EXEC usp_HelloWorldReady 'de', @GreetingDe OUTPUT;  
--German as spoken in Switzerland.  Because we don't have a specific assembly  
--for this case, the .NET Framework will automatically fall back to the neutral German culture DLL.  
EXEC usp_HelloWorldReady 'de-CH', @GreetingDe_CH OUTPUT;  
EXEC usp_HelloWorldReady 'en', @GreetingEn OUTPUT;  
EXEC usp_HelloWorldReady 'es', @GreetingEs OUTPUT;  
--French as spoken anywhere in the world (the neutral French culture)  
EXEC usp_HelloWorldReady 'fr', @GreetingFr OUTPUT  
--French as spoken in France.  Since we do have a specific assembly for this case, a specific   
--greeting is provided from that DLL.  The neutral French culture DLL is not used in this case.  
EXEC usp_HelloWorldReady 'fr-FR', @GreetingFr_FR OUTPUT  
EXEC usp_HelloWorldReady 'it', @GreetingIt OUTPUT;  
EXEC usp_HelloWorldReady 'ja', @GreetingJa OUTPUT;  
  
SELECT @GreetingDe AS OUTPUT_PARAMETER_DE;  
SELECT @GreetingDe_CH AS OUTPUT_PARAMETER_De_CH;  
SELECT @GreetingEn AS OUTPUT_PARAMETER_EN;  
SELECT @GreetingEs AS OUTPUT_PARAMETER_ES;  
SELECT @GreetingFr AS OUTPUT_PARAMETER_FR;  
SELECT @GreetingFr_FR AS OUTPUT_PARAMETER_Fr_FR;  
SELECT @GreetingIt AS OUTPUT_PARAMETER_IT;  
SELECT @GreetingJa AS OUTPUT_PARAMETER_JA;  
  
GO  

다음 Transact-SQL 데이터베이스에서 어셈블리 및 저장 프로시저를 제거합니다.

USE AdventureWorks;  
GO  
  
-- Drop existing sproc and assembly if any.  
  
IF EXISTS (SELECT * FROM sys.procedures WHERE [name] = 'usp_HelloWorldReady')  
DROP PROCEDURE usp_HelloWorldReady;  
GO  
  
IF EXISTS (SELECT * FROM sys.assemblies WHERE [name] = 'HelloWorldReady')  
DROP ASSEMBLY HelloWorldReady;  
GO  
  
IF EXISTS (SELECT * FROM sys.assemblies WHERE [name] = 'HelloWorldReady.resources.neutral')  
DROP ASSEMBLY [HelloWorldReady.resources.neutral]  
GO  
  
IF EXISTS (SELECT * FROM sys.assemblies WHERE [name] = 'HelloWorldReady.resources.de')  
DROP ASSEMBLY [HelloWorldReady.resources.de]  
GO  
  
IF EXISTS (SELECT * FROM sys.assemblies WHERE [name] = 'HelloWorldReady.resources.es')  
DROP ASSEMBLY [HelloWorldReady.resources.es]  
GO  
  
IF EXISTS (SELECT * FROM sys.assemblies WHERE [name] = 'HelloWorldReady.resources.fr')  
DROP ASSEMBLY [HelloWorldReady.resources.fr]  
GO  
  
IF EXISTS (SELECT * FROM sys.assemblies WHERE [name] = 'HelloWorldReady.resources.fr-FR')  
DROP ASSEMBLY [HelloWorldReady.resources.fr-FR]  
GO  
  
IF EXISTS (SELECT * FROM sys.assemblies WHERE [name] = 'HelloWorldReady.resources.it')  
DROP ASSEMBLY [HelloWorldReady.resources.it]  
GO  
  
IF EXISTS (SELECT * FROM sys.assemblies WHERE [name] = 'HelloWorldReady.resources.ja')  
DROP ASSEMBLY [HelloWorldReady.resources.ja]  
GO  
  
USE master;  
GO  

또한 참조하십시오

CLR(공용 언어 런타임) 통합에 대한 사용 시나리오 및 예