Compartir a través de


Ejemplo de Hello World Ready

En el ejemplo Hello World Ready se muestran las operaciones básicas implicadas en la creación, implementación y prueba de un procedimiento almacenado basado en la integración de Common Language Runtime (CLR) listo para el mundo simple. Un componente listo para el mundo se puede localizar fácilmente en diferentes idiomas para diferentes mercados de todo el mundo sin cambiar el código fuente del componente. En este ejemplo también se muestra cómo devolver datos a través de un parámetro de salida y a través de un registro, que se construye dinámicamente mediante el procedimiento almacenado y se devuelve al cliente. Este ejemplo es casi idéntico al ejemplo Hola mundo, salvo que es mucho más fácil y seguro localizar esta aplicación. Para cambiar el texto localizado, es necesario lo siguiente:

  1. Cambio de un archivo XML (el archivo .resx ) para la referencia cultural concreta en el directorio resources

  2. Creación del archivo de recursos de la referencia cultural mediante resgen

  3. Compilación del archivo DLL satélite actualizado para esa referencia cultural

  4. Quitar y agregar ese ensamblado en SQL Server

El código fuente y el ensamblado del procedimiento almacenado CLR no cambian. Se proporciona un build.cmd script que muestra cómo compilar y vincular los ensamblados de recursos. Aunque el código fuente de la aplicación crea un administrador de recursos basado en el ensamblado que se está ejecutando actualmente, no es necesario insertar los recursos neutros de referencia cultural en el archivo DLL que contiene el procedimiento almacenado. System.Resources.NeutralResourcesLanguage attribute permite que los recursos neutros de la referencia cultural existan en un archivo DLL satélite. Es mucho mejor usar un archivo DLL independiente para este propósito, de modo que cuando se necesite agregar o cambiar texto localizado, el archivo DLL principal que contiene el procedimiento almacenado CLR no tiene que cambiarse. Esto resulta especialmente útil para los tipos definidos por el usuario clR que podrían tener columnas y otras dependencias, lo que dificultaría quitar y volver a agregar el tipo. Normalmente, las versiones de DLL satélite deben ser idénticas a la versión principal del ensamblado. Sin embargo, puede usar el SatelliteContractVersion atributo para permitir que el ensamblado principal se actualice sin actualizar también los ensamblados satélite. Para obtener más información, consulte la ResourceManager clase en la documentación de Microsoft .NET.

Prerrequisitos

Este ejemplo solo funciona con SQL Server 2005 y versiones posteriores.

Para crear y ejecutar este proyecto, debe instalarse el siguiente software:

  • SQL Server o SQL Server Express. Puede obtener SQL Server Express de forma gratuita desde el sitio web de documentación y ejemplos de SQL Server Express.

  • La base de datos AdventureWorks que está disponible en el sitio web para desarrolladores de SQL Server

  • SDK de .NET Framework 2.0 o posterior o Microsoft Visual Studio 2005 o posterior. Puede obtener el SDK de .NET Framework de forma gratuita.

  • Además, se deben cumplir las siguientes condiciones:

  • La instancia de SQL Server que usa debe tener habilitada la integración clR.

  • Para habilitar la integración clR, realice los pasos siguientes:

    Habilitar la integración con CLR

    • Ejecute los siguientes comandos Transact-SQL:

    sp_configure 'clr enabled', 1

    GO

    RECONFIGURE

    GO

    Nota:

    Para habilitar CLR, debe tener ALTER SETTINGS permiso de nivel de servidor, que se mantiene implícitamente en los miembros de los sysadmin roles fijos de servidor y serveradmin .

  • La base de datos AdventureWorks debe instalarse en la instancia de SQL Server que está usando.

  • Si no es administrador para la instancia de SQL Server que usa, debe tener un permiso de administrador para crearAssembly para completar la instalación.

Compilar el ejemplo

Cree y ejecute el ejemplo mediante las instrucciones siguientes:

  1. Abra un símbolo del sistema de Visual Studio o .NET Framework.

  2. Si es necesario, cree un directorio para el ejemplo. En este ejemplo, usaremos C:\MySample.

  3. En c:\MySample, cree HelloWorld.vb (para el ejemplo de Visual Basic) o HelloWorld.cs (para el ejemplo de C#) y copie el código de ejemplo de Visual Basic o C# adecuado (a continuación) en el archivo.

  4. En c:\MySample, cree el archivo messages.resx y copie el código de ejemplo en el archivo.

  5. En c:\MySample, cree el archivo messages.de.resx guardando el archivo messages.resx como messages.de.resx después de cambiar la línea.

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

    • Leer

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

  6. En c:\MySample, cree el archivo messages.es.resx guardando el archivo messages.resx como messages.es.resx después de cambiar la línea.

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

    • Leer

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

  7. En c:\MySample, cree el archivo messages.fr.resx guardando el archivo messages.resx como messages.fr.resx después de cambiar la línea.

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

    • Leer

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

  8. En c:\MySample, cree el archivo messages.fr-FR.resx guardando el archivo messages.resx como messages.fr-FR.resx después de cambiar la línea.

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

    • Leer

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

  9. En c:\MySample, cree el archivo messages.it.resx guardando el archivo messages.resx como messages.it.resx después de cambiar la línea.

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

    • Leer

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

  10. En c:\MySample, cree el archivo messages.ja.resx guardando el archivo messages.resx como messages.ja.resx después de cambiar la línea.

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

    • Leer

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

  11. En c:\MySample, cree el archivo build.com y copie el código de ejemplo en el archivo.

  12. Compile los ensamblados satélite ejecutando la compilación del archivo en el símbolo del sistema.

  13. Compile el código de ejemplo desde el símbolo de la línea de comandos ejecutando uno de los siguientes:

    • 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. Si el ejemplo está instalado en un directorio distinto, C:\MySample\edite el archivo Install.sql como se indica para que apunte a esa ubicación.

  15. Implementación del ensamblado y el procedimiento almacenado mediante la ejecución

    • sqlcmd -E -I -i install.sql
  16. Copie Transact-SQL script de comando de prueba en un archivo y guárdelo como test.sql en el directorio de ejemplo.

  17. Ejecute el script de prueba con el comando siguiente.

    • sqlcmd -E -I -i test.sql
  18. Copie el script de limpieza Transact-SQL en un archivo y guárdelo como cleanup.sql en el directorio de ejemplo.

  19. Ejecute el script con el comando siguiente.

    • sqlcmd -E -I -i cleanup.sql

Código de ejemplo

A continuación se muestran las listas de código de este ejemplo.

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  
  

Se trata de build.com, que compila los ensamblados satélite.

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  

Este es el script de instalación de Transact-SQL (Install.sql), que implementa los ensamblados y crea el procedimiento almacenado dentro de la base de datos.

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  

Se trata de test.sql, que prueba el ejemplo mediante la ejecución de las funciones en cada configuración regional.

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  

El siguiente Transact-SQL quita los ensamblados y el procedimiento almacenado de la base de datos.

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  

Véase también

Escenarios de uso y ejemplos para la integración de Common Language Runtime (CLR)