Llamar a servicios web desde dentro de SQL Server 2005

El otro día, por diversión, me dio por jugar a llamar a un servicio web desde un procedimiento almacenado de SQL Server 2005 escrito en C#. La cosa parecía fácil y divertida, pero de eso nada, no había manera de hacer funcionar aquello…. Por fin, después de buscar un rato por el Google encontré la solución a mis problemas. Para evitar que a vosotros también os pase lo mismo, quisiera compartir con todos vosotros esta experiencia que os permitirá saber de antemano los problemas que os vais a encontrar al hacer este tipo de cosas y como solucionarlos.


Para empezar supongamos que tenemos una solución en Visual Studio 2005 con un sitio web donde está definido el siguiente servicio web accesible mediante la url http://localhost/ServiciosWeb/ServicioWeb.asmx


public class ServicioWeb : System.Web.Services.WebService

  [WebMethod] 
  public string RealizarProceso(int IdProceso) 
  { 
    if (IdProceso % 5 == 0) 
    { 
      throw new SoapException(«No me gustan los múltiplos de cinco»,
                               SoapException.ClientFaultCode); 
    } 
    else 
    {
      return «Proceso número » + IdProceso.ToString() +
             » realizado correctamente»; 
    } 
  }
}



Supongamos también que creamos un proyecto de SQL Server de nombre ServiciosWebClr. Lo primero que se nos ocurre es añadir una referencia web al servicio, a la que llamamos ServiciosWeb. Luego añadirmos un procedimiento almacenado llamado RealizarProceso con este código:



using System.Data.SqlTypes;
using Microsoft.SqlServer.Server;
using ServiciosWebClr.ServiciosWeb;



public partial class StoredProcedures
{
  [Microsoft.SqlServer.Server.SqlProcedure]
  public static void RealizarProceso(SqlInt32 IdProceso)
  {
    using (ServicioWeb sw = new ServicioWeb())
    {
      string Resultado = sw.RealizarProceso(IdProceso.Value);
    }
  }
};



Para que un procedimiento almacenado CLR pueda llamar a un servicio web, el ensamblado en el que reside tiene que tener permiso de EXTERNAL ACCESS. Para ello vamos a las propiedades del proyecto, ficha database y seleccionamos external en el cuadro combinado permission level. Pero esto no es suficiente. Si intentamos desplegar (deploy) el proyecto recibiremos el siguiente error:



CREATE ASSEMBLY for assembly ‘ServiciosWebClr’ failed because assembly ‘ServiciosWebClr’ is not authorized for PERMISSION_SET = EXTERNAL_ACCESS.  The assembly is authorized when either of the following is true: the database owner (DBO) has EXTERNAL ACCESS ASSEMBLY permission and the database has the TRUSTWORTHY database property on; or the assembly is signed with a certificate or an asymmetric key that has a corresponding login with EXTERNAL ACCESS ASSEMBLY permission. ServiciosWebClr



Para solucionarlo ejecutamos la siguiente sentencia en el Management Studio:



ALTER DATABASE <base de datos> SET TRUSTWORTHY ON



Con esto ya podremos desplegar el proyecto en SQL Server. Pero si ejecutamos este procedimiento almacenado en el Management Studio, nos encontramos con otro problema, recibimos el siguiente mensaje de error:



Msg 6522, Level 16, State 1, Procedure RealizarProceso, Line 0
A .NET Framework error occurred during execution of user defined routine or aggregate ‘RealizarProceso’:
System.InvalidOperationException: Cannot load dynamically generated serialization assembly. In some hosting environments assembly load functionality is restricted, consider using pre-generated serializer. Please see inner exception for more information. —> System.IO.FileLoadException: LoadFrom(), LoadFile(), Load(byte[]) and LoadModule() have been disabled by the host.
etc etc.



Los servicios web serializan y deserializan los objetos en formato XML. Para realizar estas operaciones utilizan un XmlSerializer el cual genera y carga en tiempo de ejecución un ensamblado con clases especializadas en serializar y deserializar los tipos de nuestro  ensamblado. Por razones de seguridad y fiabilidad, SQL Server no permite cargar ensamblados en tiempo de ejecución, por eso recibimos esta excepción.


La solución, como sugiere el mesaje de error, es utitlizar un serializador XML pregenerado. Entre las herramientas de línea de comandos, tenemos SGen.exe que genera un ensamblado para serialización XML. Pero es más sencillo ir a las propiedades del proyecto, ficha build y seleccionar on en el cuadro combinado generate serialization assembly. Con esto, se generará el ensamblado ServiciosWebClr.XmlSerializers.dll cada vez que generemos el proyecto. Pero este ensamblado no se instala automáticamente en SQL Server, tenemos que hacerlo nosotros manualmente. Para ello añadimos los scripts predeployscript.sql y postdeployscript.sql en la raíz del proyecto (no en la carpeta Test Scripts) con el siguiente contenido:



Predeployscript.sql:



IF EXISTS (SELECT [name]
           FROM sys.assemblies
           WHERE [name] = N’ServiciosWebClr.XmlSerializers’)
DROP ASSEMBLY [ServiciosWebClr.XmlSerializers]
WITH NO DEPENDENTS



Postdeployscript.sql:



CREATE ASSEMBLY [ServiciosWebClr.XmlSerializers]
FROM ‘<path>ServiciosWebClr.XmlSerializers.dll’


Con esto ya debería funcionar.



Otra cuestión es que la mayoría de las veces no resulta adecuado llamar al servicio web de forma síncrona, ya que normalmente la llamada tarda algunos segundos. Así que veamos qué pasa cuando llamamos a los servicios web de forma asíncrona.


Supongamos que creamos la siguiente tabla y procedimiento almacenado para registrar todas las llamadas al servicio web, incluyendo el resultado, información de tiempos y errores:



CREATE TABLE RegistroProcesos
(
      IdRegistro int IDENTITY(1,1) PRIMARY KEY,
      IdProceso int NOT NULL,
      Comienzo datetime NOT NULL,
      Fin datetime NOT NULL,
      Correcto bit NOT NULL DEFAULT 1,
      Resultado varchar(100),
      DescripcionError varchar(1000)
)

GO
 
CREATE PROCEDURE RegistrarProceso
      @IdProceso int,
      @Comienzo datetime,
      @Fin datetime,
      @Correcto bit,
      @Resultado varchar(100),
      @DescripcionError varchar(1000)
AS
      INSERT INTO RegistroProcesos(
            IdProceso, Comienzo, Fin,
            Correcto, Resultado, DescripcionError)
      VALUES (
            @IdProceso, @Comienzo, @Fin,
            @Correcto, @Resultado, @DescripcionError)


Nuestra clase StoredProcedures podría ser la siguiente:


public partial class StoredProcedures
{


  private class Estado
  {
    public int IdProceso;
    public ServicioWeb ServicioWeb;
    public DateTime Comienzo;
 
    public Estado(
        int IdProceso,
        ServicioWeb ServicioWeb,
        DateTime Comienzo)
    {
      this.IdProceso = IdProceso;
      this.ServicioWeb = ServicioWeb;
      this.Comienzo = Comienzo;
    }
  }
 
  [Microsoft.SqlServer.Server.SqlProcedure]
  public static void RealizarProceso(SqlInt32 IdProceso)
  {
    ServicioWeb sw = new ServicioWeb();
    Estado Estado = new Estado(IdProceso.Value, sw, DateTime.Now);
    sw.BeginRealizarProceso(
          IdProceso.Value, DelegadoProcesoRealizado, Estado);
  }
 


  private static readonly AsyncCallback DelegadoProcesoRealizado =
       new AsyncCallback(ProcesoRealizado);
 
  private static void ProcesoRealizado(IAsyncResult ar)
  {
    Estado Estado = (Estado)ar.AsyncState;
    try
    {
      String Resultado = Estado.ServicioWeb.EndRealizarProceso(ar);
      RegistrarProceso(Estado.IdProceso, Estado.Comienzo,
                       DateTime.Now, true, Resultado, null);
    }
    catch (Exception ex)
    {
      RegistrarProceso(Estado.IdProceso, Estado.Comienzo,
                       DateTime.Now, false, null, ex.Message);
    }
   }
 
   private const string ConnectionString =
     «Data Source=(local);Integrated Security=SSPI;» +
     «Initial Catalog=AdventureWorks»;
 
 
   private static void RegistrarProceso(
     int IdProceso,   
     DateTime Comienzo,
     DateTime Fin,
     bool Correcto,
     string Resultado,
     string DescripcionError)
   {
     using (SqlConnection cn = new SqlConnection(ConnectionString))
     using (SqlCommand cmd = new SqlCommand(«RegistrarProceso», cn))
     {
       cmd.CommandType = CommandType.StoredProcedure;
       cmd.Parameters.Add(«@IdProceso», SqlDbType.Int).Value =
           IdProceso;
       cmd.Parameters.Add(«@Comienzo», SqlDbType.DateTime).Value =
           Comienzo;
       cmd.Parameters.Add(«@Fin», SqlDbType.DateTime).Value = Fin;
       cmd.Parameters.Add(«@Correcto», SqlDbType.Bit).Value =
           Correcto;
       cmd.Parameters.Add(«@Resultado»,SqlDbType.VarChar, 100).Value =
           Resultado == null ? (object) DBNull.Value :
                        (object) Resultado;
       cmd.Parameters.Add(«@DescripcionError»,
                          SqlDbType.VarChar, 1000).Value =
       DescripcionError == null ? (object) DBNull.Value :
                           (object) DescripcionError;
       cn.Open();
       cmd.ExecuteNonQuery();
     }


   }
}


Observa que la cadena de conexión no es «context connection=true», sino una cadena de conexión regular. Esto es así porque el método de devolución de llamada ProcesoRealizado se ejecuta en un hilo diferente que el procedimiento almacenado, este hilo no es un hilo de ejecución de SQL Server así que no se puede usar la conexión de contexto.


Si desplegamos ahora el proyecto y ejecutamos lo siguiente en el ManagementStudio:


TRUNCATE TABLE RegistroProcesos
DECLARE @IdProceso int
SET @IdProceso = 1
WHILE @IdProceso <= 10
BEGIN
  EXEC RealizarProceso @IdProceso
  SET @IdProceso = @IdProceso + 1
END


Y luego ejecutamos;


SELECT * FROM RegistroProcesos


Veremos que el procedimiento almacenado funciona como se espera.


Pues nada más, espero que esto os sirva de ayuda y os quite algún que otro quebradero de cabeza si es que alguna vez necesitáis llamar a un servicio web desde dentro de SQL Server 2005.


Un saludo:


Jesús López
 

30 comentarios sobre “Llamar a servicios web desde dentro de SQL Server 2005”

  1. muy bueno… siempre intentaria evitar llamar a un webservice desde un store pero este es el típico link k voy a tener en favoritos ( nunca se sabe y el tema de la sys.assemblies mejor tenerlo presente ).

  2. Sí, estoy de acuerdo en que generalmente, si lo puedes evitar, no será una buena idea llamar a un servicio web desde un procedimiento almacenado. Sin embargo pueden existir situaciones en las que sea lo más conveniente. Por ejemplo imagina que tienes un sistema con una base de datos y varias aplicaciones accediendo a esa base de datos. Tú tienes control sobre la base de datos pero no sobre las aplicaciones y necesitas realizar una determinada acción cuando se inserte un registro en una determinada tabla. Supón además que en esa accíón conlleva acceso a recursos externos. Una posible solución es crear un trigger en la tabla que llame un servicio web.

  3. Yo creo, que es la típica cosa que esta bien como curiosidad y que puede tener su aplicaciones, no lo niego.

    Pero la idea a lanzar y que, en mi opinión, debe quedar clara es que, en principio, llamar a un web service desde un procedimiento almacenado, o peor aun, desde un trigger no es, casi nunca, una buena idea. Es algo que puede resultar desastroso para la escalabilidad de una aplicación. Y lo malo es que a primera vista, con poco trasiego en la base de datos va a funcionar, perfectamente.

    Yo creo que la maxima es «si el clr biene desactivado por defecto en Sql Server, por algo será»

  4. No ha sido mi intención con este blog animar a la gente a llamar a servicios web desde SQL Server, sino explicar cómo se puede hacer.

    Vuelvo a repetir que generalmente no será una buena idea. Pero tampoco será tan desastroso para la escalabilidad de una aplicación a no ser que la frecuencia de llamadas sea grande. Puedes invocar perfectamente a un servicio web en un trigger siempre que lo hagas de forma asíncrona y no produzca que se llame al servicio web demasiado a menudo.

    Con esto quiero dejar claro que llamar a servicios web desde una base de datos es una herramienta más de la que disponemos los desarrolladores y que no es ni buena ni mala, todo dependerá del uso que se vaya a hacer de ella.

  5. A veces hablamos guiados por nuestra experiencia e intuición. Sin embargo no hay nada como la medición para estar seguros de lo que estamos hablando.

    He hecho una pequeña prueba para tener una idea de lo que le cuesta a SQL Server llamar a un servicio web. Esta prueba consiste en lanzar 10 hilos que simultáneamente, en una aplicación Windows, están llamando a un procedimiento almacenado que a su vez llama de forma síncrona al servicio web. Los hilos están funcionando hasta que se producen 100.000 llamadas al procedimiento almacenado. Todo se ejecuta en mi portátil que es un centrino con 512 Mb de RAM.

    Los resultados son bastante alentadores, a SQL Server le está costando 0,6 milisegundos de procesador ejecutar el procedimiento almacenado que hace la llamada al servicio web. ¿A que es muy barato?.

    El proceso de llamar 100.000 veces al procedimiento almacenado llevó 140 segundos en completarse. Durante estos 140 segundos el procesador estaba constantemente al 100%. Así que nos salen 1,4 milisegundos de procesador por ejecución. Sin embargo esos 1,4 milisegundos los gasta el procesador entre varios procesos:

    SQL Server se lleva el 43%
    ASP.NET el 32 %
    El IIS el 17%
    System el 4%
    WinText.exe el 4%

    Así que SQL Server gasta el 43% de los 1,4 milisegundos que son 0,6 milisegundos.

    Desde luego esta prueba no es concluyente. Todo está en local y el servicio web es muy chiquitín, el método recibe un entero y devuelve un string, poquita cosa. Con servicios web más pesados seguro que la cosa cambia. Pero esta prueba demuestra que llamar a un servicio web desde SQL Server no es tan costoso como podría parecer, sino todo lo contrario, con servicios web chiquitines el coste en procesador es mínimo.

    A ver quien se anima a hacer otras pruebas.

  6. 🙂 toy de acuerdo que es una posibilidad más y eso es lo importante ( igual que utilizar los asistentes del visual studio, poner las selects como churros en el codigo, las conexiones hardcode etc… )

    Lo importante es el uso que se le da, y evidentemente comparto que sea como sea la llamada ha de ser asincrona porque sino no tiene ninguna logica cosa que para que sea util la llamada y sea asincrona ya limita muchisimo los casos donde se pueda utlizar.

    Mi opinion : Por bueno la verdad.. las maquinas que sufren mas el peso ( por lo menos en mi experiencia ) siempre son los servidores de sql y normalmente no dejo que se atake directamente cualquiera, es decir si quieres acceder a mi sql sever lo tendras que hacer por un web service que yo te proporcione o una app mia.. por lo que si tengo un web farm por ejemplo yo personalmente pondria la llamada al web service en los demas servidores nunca en el sql server k pobrecito ya tiene bastante ( si es que hay que mimarlos! ).

    Pero claro como bien comentas seguro que existe algun caso en el que esto es necesario ( como dices en el caso» Tú tienes control sobre la base de datos pero no sobre las aplicaciones » ) y seguro que por eso se implemento, como una posibilidad más y sino como bien comentas al principio del thread …»El otro día, por diversión…» k ya es un buen motivo, unos juegan a la play otros haces sp que llaman servicios webs juas juas

  7. Muy bueno! Muchas gracias, con esta ayuda lo hice andar en 5 minutos.
    Realmente en mi caso no me quedaba otra salida, ya que la unica interfaz de entrada al sistema es via sp.
    Saludos

  8. que tal a todos: ando empezando una aplicacion visual basic 2005 en la cual voy a hacer uso de los catalogos de otra aplicacion existente ya en el servidor, como me recomiendan extraer la informacion de la aplicacion que ya existe. que tal me recomiendan un servicio web

    Saludos !

  9. Pues la verdad es que no, ya que la pregunta no tiene nada que ver con el artículo. No es posible dar una repuesta adecuada por la falta de detalles y para resolver dudas ya están los grupos de noticias

  10. Julio,

    SQL Server 2000 no está integrado con el .NET CLR, por tanto no se puede hacer un procedimiento almacenado escrito en C# o VB para llamar a un servicio web.

    Sin embargo SQL Server 2000 tiene otros mecanismos para acceder a recursos externos. Estos son:

    1) Procedimientos almacenados extendidos. Puedes escribir un procedimiento almacenado extendido en C++ y registrarlo en SQL Server. Este tipo de procedimientos pueden hacer prácticamente cualquier cosa que se pueda progrmar en C++. El inconveniente es que C++ produce código no gestionado y como los procedimientos almacenados extendidos se ejecutan en el mismo proceso y espacio de direcciones de SQL Server, existe el riesgo de que un defecto en el procedimiento corrompa la memoria o intente acceder a direcciones no reservadas del proceso, con lo que el procedimiento podría tirar SQL Server. Por eso los administradores de base de datos son bastante reticentes a la hora de registrar un procedimiento almacenado extendido personalizado.

    2) Automatización COM. SQL Server dispone de los procedimientos almacenados extendidos sp_OACreate sp_OAMethod etc que permiten crear y utilizar componentes de automatización COM. Podría crease una dll ActiveX en VB 6.0 que expusiera una serie de métodos para llamar a un determinado servicio web. Y desde un procedimiento almacenado y usando los procedimientos SP_OA acceder a la dll ActiveX para llamar al servicio web. La dll ActiveX podría usar el objeto XmlHttpRequest para construir la llamada SOAP y hacer la llamada al servicio web de forma asíncrona. Otra posibilidad es usar el SOAP Toolkit, pero tiene el inconveniente de que las llamadas son síncronas, lo que no es nada adecuado cuando se trata de llamar a un servicio web desde SQL Server.

  11. Estimado Jesús.

    Agradesco de sobremanera tu buena disposición y tiempo que haz tomado para responder mi pregunta. Y aprevecho de felicitarte por tan buen blog.

  12. YO tengo un caso en el cual es necesario ejecutar un servicio web desde un proc almacenado o desde un trigger.
    Mi caso es el siguiente: En una base de datos oracle un proceso externo insertara en una tabla INPUT, de la cual yo tengo q detectar esa insersion y ejecutar un servicio web que haga consultas a una base de datos sql server 2005 y luego como resultado inserte un registro en una tabla OUT de oracle.
    Para esto es necesario correr un proc almacenado o un trigger que llame al servicio web y posteriormente se haga la insersion a la tabla OUT.

    Lo complicado para mi es q no tengo experiencia en oracle ya que trabajo con sql server, asi que tendre q ver como realizar esta operacion.
    Espero puedan darme algunas pautas.

    Gracias de antemano.

  13. una pregunta. como se ejecutan el predeploy y el postdeploy? es decir. tendrás que darles alguna orden de ejecución o algo asi para que sepan en que orden van y ese tipo de cosas,no?lo digo porque a mi no me crea el assembly en la base de datos a no ser que lo ejecute yo directamente sobre el sql server. saludos

  14. los scripts Predeployscript.sql y Postdeployscript.sql se ejecutan automáticamente siempre que sus nombres sean correctos y estén en la carpeta raíz del proyecto.

  15. Msg 6522: Segun ya hice todos los pasos que mencionan, pero me sigue saliendo el mensaje 6522 que podre haber hecho mal, si al ensamblado le quito la llamada al webservice funciona bien pero cuando llama al webservice marca el error.

  16. hola Jesus,
    Quiero saber si esto tambien aplica para ejecutar una dll de . net programada en VB2003 el fin es que deseo ejecutar uno de los metodos de esta dll periodicamente en un Job

    Gracias Saludos

  17. Con todo respeto a la gente como Rodrigo Corral, creo que no deberían perder el norte de este articulo, la verdad a mi me ha salvado la vida (y quizás a muchos más)…
    Me revienta la gente que se mete a opinar de forma despectiva o sin darle mayor relevancia a las cosas, mejor sería que no opinaran, si la máxima fuera esa del CLR, yo podría decir algo parecido «si SQL Server permite ejecutar servicios web, por algo será» puntos de vista Rodrigo, pero a mi me parece que en todo caso, antes de ponerte a hablar de escalabilidad y cosas asi mejor sería desarrollar un poco el concepto de humildad y saber aprovechar lo bueno, SQLRanger me evitó mil problemas con este artículo y la verdad, a mi me pareció excelente…

  18. Hola buenos dias,
    estuve leyendo tu articulo para llamar un servicio web desde un procedimiento almacenado y me ha servido muchisimo, pero tengo un problema cuando genero el ensamblado serializado.
    Cuando creo el assembly en el servidor SQL, no me coloca ningun problema, pero cuando quiero convertirlo a un procedimiento almacenado mediante la instruccion:
    CREATE PROCEDURE sp_Projects
    AS
    EXTERNAL NAME [NVSDocumentManagment.SqlClient].[StoredProcedures].[GetProject]
    por lo que es un xml no puedo acceder al metodo getproject, ni ala clase que es storedprocedures, y cuando creo el assembly con el ensamblado normal me sale el error que debo serializarlo.
    Me podrias ayudar de algun modo.

    Mil gracias.
    Jorge

  19. Hola Jesús, que tal tanto tiempo.
    Podrías explicarme por favor porque consideras una ventaja hacer la llamada asincónica? Según mi entender, una llamada asincronica se ejecuta sobre un hilo secundario. Este hilo secundario, se toma del thread pool de SQL Server, no?
    De ser así, no sería hasta contraproducente entonces hacer la llamada asincónica, lo cual consumiría 2 threads en lugar de uno?
    Gracias

  20. Me corrijo, mientras el hilo secundario se ejecuta, el principal se libera y vuelve al pool.
    De todas formas, si bien no creo que empeore la situación, veo que la ganancia no es tal. Ya que siempre estoy consumiendo un hilo del pool.
    Gracias

  21. Hola,

    Yo hice una dll que cargo como assembly en SQL2005 para llamar un WebService; pero al ejecutarlo no hace nada, lo debugue con el VS y si llega a la parte en que llama al WS pero no realiza los cambios y tampoco marca error. Pero cuando ejecuto el WS directo si realiza los cambios.

    Aque se puede deber esto??

  22. segui todos los pasos y me sigue dando el error
    Mens 6522, Nivel 16, Estado 1, Procedimiento uspPedidos, Línea 0
    Error de .NET Framework durante la ejecución de la rutina o agregado definido por el usuario «uspPedidos»:
    System.InvalidOperationException: Cannot load dynamically generated serialization assembly. In some hosting environments assembly load functionality is restricted, consider using pre-generated serializer. Please see inner exception for more information. —> System.IO.FileLoadException: LoadFrom(), LoadFile(), Load(byte[]) and LoadModule() have been disabled by the host.
    System.IO.FileLoadException:
    at System.Reflection.Assembly.nLoadImage(Byte[] rawAssembly, Byte[] rawSymbolStore, Evidence evidence, StackCrawlMark& stackMark, Boolean fIntrospection)
    at System.Reflection.Assembly.Load(Byte[] rawAssembly, Byte[] rawSymbolStore, Evidence securityEvidence)
    at Microsoft.CSharp.CSharpCodeGenerator.FromFileBatch(CompilerParameters options, String[] fileNames)
    at Microsoft.CSharp.CSharpCodeGenerator.FromSourceBatch(CompilerParameters options, String[] sources)
    at Microsoft.CSharp.CSharpCodeGenerator.System

    espero alguien me pueda ayudar
    este es mi correo zok.1708@hotmail.com

  23. hola: soy novato en esto, por lo que tengo muchas dudas sobre el tema; pero la principal es en la que necesito mostrar los datos guardados en pervasive sql server en sql server compaq para windows CE 5.0; ya que estoy realizando la aplicacion para un microkiosk motorola. cualquier comentario seria de gran ayuda.
    A y muy buen aporte tu articulo.

  24. Que tal amigos. La respuesta va para los que han preguntado si es posible llamar un web services desde un SP en SQL 2000.
    La respuesta es si. Es mucho mas complejo y no tan eficiente como en 2005-2008, pero aqui les va:
    – Se crea un SP que ejecute un DTS con el comanto DTexec (deben tener activada la variable de configuracion xp-cmd). Es decir que no en todos los server podran hacerlo.

    – Se crea el DTS con un proceso ACTIVEX que contenga el codigo en VB para llamar Web Services. Si se necesita leer el retorno del WS lo pueden almacenar en una tabla o por variables globales. Como llamar un web services desde ASP o VB se hace con los objetos MSXML2.XMLHTTP y MSXML.DOMDocument, tal y como lo hariamos en Javascript para el AJAX.

    Y listo.
    En conclusion, el Sp llama un DTS que llama el WS.

  25. @Carlos Walzer:

    El beneficio de la llamada asíncrona es múltiple. Por una parte la llamada al procedimiento almacenado vuelve antes de que se termine la llamada al servicio web. Por otra parte no es cierto que se esté consumiendo un hilo del Thread Pool mientras se está ejecutando la llamada al servicio web. Cuando la respuesta del servicio web llega, se toma un hilo del Thread Pool para procesar la respuesta, en vez de mantener un hilo activo simplemente esperando a que termine el servicio web.

Responder a rcorral Cancelar respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *