Freigeben über


Beispiel für "Hello World Ready"

Das Hello World Ready-Beispiel veranschaulicht die grundlegenden Vorgänge, die beim Erstellen, Bereitstellen und Testen einer einfachen gespeicherten World-Ready-Prozedur auf der Basis einer CLR (Common Language Runtime)-Integration ausgeführt werden müssen. Eine World-Ready-Komponente lässt sich problemlos in verschiedene Sprachen für unterschiedliche Märkte in aller Welt lokalisieren, ohne den Quellcode der Komponente zu ändern. Dieses Beispiel zeigt außerdem, wie Sie Daten über einen Ausgabeparameter und einen Datensatz, der dynamisch von der gespeicherten Prozedur erstellt und an den Client zurückgegeben wird, zurückgeben können. Das Beispiel ist fast identisch mit dem Hello World-Beispiel, die Anwendung ist jedoch einfacher und sicherer zu lokalisieren. Das Ändern von lokalisiertem Text erfordert Folgendes:

  1. Ändern einer XML-Datei (die resx-Datei) für die bestimmte Kultur im Ressourcenverzeichnis

  2. Erstellen der Ressourcendatei der Kultur mithilfe von resgen

  3. Erstellen der aktualisierten Satelliten-DLL für diese Kultur

  4. Löschen und Hinzufügen dieser Assembly in SQL Server

Der Quellcode und die Assembly für die eigentliche gespeicherte CLR-Prozedur bleiben unverändert. Ein build.cmd-Skript wird bereitgestellt, das veranschaulicht, wie die Ressourcenassemblys kompiliert und verknüpft werden. Obwohl der Quellcode der Anwendung einen Ressourcen-Manager auf der Basis der aktuell ausgeführten Assembly erstellt, müssen Sie die kulturneutralen Ressourcen nicht in die DLL einbetten, die die gespeicherte Prozedur enthält. Das System.Resources.NeutralResourcesLanguage attribute lässt die kulturneutralen Ressourcen in einer Satelliten-DLL zu. Es empfiehlt sich, für diesen Zweck eine separate DLL zu verwenden, damit die primäre DLL, in der sich die gespeicherte CLR-Prozedur befindet, nicht geändert werden muss, wenn lokalisierter Text hinzugefügt oder geändert werden muss. Dies erweist sich vor allem für benutzerdefinierte CLR-Typen als hilfreich, die möglicherweise Spalten und andere Abhängigkeiten beinhalten, die es schwierig machen, den Typ zu löschen und erneut hinzuzufügen. Normalerweise müssen die Satelliten-DLL-Versionen mit der Version der Hauptassembly übereinstimmen. Sie können jedoch das SatelliteContractVersion-Attribut dazu verwenden, das Update der Hauptassembly zuzulassen, ohne gleichzeitig die Satellitenassemblys zu aktualisieren. Weitere Informationen finden Sie in der ResourceManager-Klasse in der Microsoft .NET-Dokumentation.

Voraussetzungen

Dieses Beispiel kann nur mit SQL Server 2005 und höheren Versionen ausgeführt werden.

Zum Erstellen und Ausführen dieses Projekts muss die folgende Software installiert sein:

  • SQL Server oder SQL Server Express. SQL Server Express erhalten Sie kostenlos auf der Website mit der Dokumentation und den Beispielen für SQL Server Express.

  • Die AdventureWorks-Datenbank, die auf der SQL Server Developer-Website zur Verfügung gestellt wird.

  • .NET Framework SDK 2.0 oder höher oder Microsoft Visual Studio 2005 oder höher. Das .NET Framework SDK ist kostenlos erhältlich.

  • Außerdem müssen die folgenden Bedingungen erfüllt sein:

  • In der von Ihnen verwendeten SQL Server-Instanz muss die CLR-Integration aktiviert sein.

  • Führen Sie zum Aktivieren der CLR-Integration die folgenden Schritte aus:

    Aktivieren der CLR-Integration

    • Führen Sie die folgenden Transact-SQL-Befehle aus:

    sp_configure 'clr enabled', 1

    GO

    RECONFIGURE

    GO

    HinweisHinweis

    Um CLR zu aktivieren, benötigen Sie die ALTER SETTINGS-Serverberechtigung, die Mitglieder der festen Serverrollen sysadmin und serveradmin implizit erhalten.

  • Die AdventureWorks-Datenbank muss in der von Ihnen verwendeten SQL Server-Instanz installiert sein.

  • Falls Sie kein Administrator für die verwendete SQL Server-Instanz sind, muss Ihnen ein Administrator die CreateAssembly -Berechtigung erteilen, damit Sie die Installation ausführen können.

Erstellen des Beispiels

Verwenden Sie die folgenden Anweisungen, um das Beispiel zu erstellen und auszuführen:

  1. Wechseln Sie zu einer Visual Studio- oder .NET Framework-Eingabeaufforderung.

  2. Erstellen Sie ggf. ein Verzeichnis für das Beispiel. Für dieses Beispiel wird C:\MySample verwendet.

  3. Erstellen Sie in c:\MySample die Datei HelloWorld.vb (für das Visual Basic-Beispiel) oder HelloWorld.cs (für das C#-Beispiel), und kopieren Sie den entsprechenden Visual Basic- oder C#-Beispielcode (unten) in die Datei.

  4. Erstellen Sie in c:\MySample die Datei messages.resx, und kopieren Sie den Beispielcode in die Datei.

  5. Erstellen Sie in c:\MySample die Datei messages.de.resx, indem Sie die Datei messages.resx als messages.de.resx speichern, nachdem Sie die Zeile

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

    • wie folgt geändert haben:

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

  6. Erstellen Sie in c:\MySample die Datei messages.es.resx, indem Sie die Datei messages.resx als messages.es.resx speichern, nachdem Sie die Zeile

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

    • wie folgt geändert haben:

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

  7. Erstellen Sie in c:\MySample die Datei messages.fr.resx, indem Sie die Datei messages.resx als messages.fr.resx speichern, nachdem Sie die Zeile

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

    • wie folgt geändert haben:

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

  8. Erstellen Sie in c:\MySample die Datei messages.fr-FR.resx, indem Sie die Datei messages.resx als messages.fr-FR.resx speichern, nachdem Sie die Zeile

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

    • wie folgt geändert haben:

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

  9. Erstellen Sie in c:\MySample die Datei messages.it.resx, indem Sie die Datei messages.resx als messages.it.resx speichern, nachdem Sie die Zeile

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

    • wie folgt geändert haben:

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

  10. Erstellen Sie in c:\MySample die Datei messages.ja.resx, indem Sie die Datei messages.resx als messages.ja.resx speichern, nachdem Sie die Zeile

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

    • wie folgt geändert haben:

    • <value xml:space="preserve"> ã?“ã‚“ã?«ã?¡ã?¯</value>

  11. Erstellen Sie in c:\MySample die Datei build.com, und kopieren Sie den Beispielcode in die Datei.

  12. Erstellen Sie die Satellitenassemblys, indem Sie den Dateibuild an der Eingabeaufforderung ausführen.

  13. Kompilieren Sie den Beispielcode aus der Eingabeaufforderung, indem Sie eine der folgenden Anweisungen ausführen:

    • 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. Wenn das Beispiel in einem anderen Verzeichnis als C:\MySample\ installiert ist, bearbeiten Sie die Datei Install.sql wie gezeigt, damit sie auf diesen Speicherort zeigt.

  15. Stellen Sie die Assembly und die gespeicherte Prozedur bereit, indem Sie die folgende Anweisung ausführen:

    • sqlcmd -E -I -i install.sql
  16. Kopieren Sie das Transact-SQL-Testbefehlsskript in eine Datei, und speichern Sie diese als test.sql im Beispielverzeichnis.

  17. Führen Sie das Testskript mit dem folgenden Befehl aus:

    • sqlcmd -E -I -i test.sql
  18. Kopieren Sie das Transact-SQL-Bereinigungsskript in eine Datei, und speichern Sie diese als cleanup.sql im Beispielverzeichnis.

  19. Führen Sie das Skript mit dem folgenden Befehl aus:

    • sqlcmd -E -I -i cleanup.sql

Beispielcode

Die Codelistings für dieses Beispiel lauten wie folgt.

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

Dies ist die Datei build.com, mit der die Satellitenassemblys erstellt werden.

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

Dies ist das Transact-SQL-Installationsskript (Install.sql), mit dem die Assemblys bereitgestellt werden und die gespeicherte Prozedur in der Datenbank erstellt wird.

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

Dies ist die Datei test.sql, mit der das Beispiel durch Ausführen der Funktionen für jedes Gebietsschema getestet wird.

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

Im folgenden Transact-SQL-Code werden die Assemblys und die gespeicherte Prozedur aus der Datenbank entfernt.

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

Siehe auch

Konzepte

Verwendungsszenarien und Beispiele für Common Language Runtime (CLR)-Integration