Salvador Ramos y Miguel Egea
Mejoras no funcionales
create table Empleados ( idEmpleado int identity (1,1) primary key,
NombreEmpleado varchar(100) ,
idJefe int,
constraint fk_jefeempleado foreign key (idjefe) references Empleados (idEmpleado))
go
insert
with
(
select
cast(cast (row_number() over( order by idEmpleado) as varchar(100))+'.'as varchar(100)) jerarquia
from
where
union
cast (jerarquia+cast (row_number() over( order by e.idEmpleado) as varchar(100))+'.' as varchar(100))
from empleados E inner join
cte on e.idJefe=cte.idEmpleado
)
El resultado de la ejecución es
id Nombre JEFE idjefe jerarquia 1 Javier El jefe JEFE NULL 1. 2 Miguel Empleado Javier El jefe 1 1.1. 5 luis Empleado Miguel Empleado 2 1.1.1. 3 Pepe El jefe JEFE NULL 2. 4 antonio Empleado Pepe El jefe 3 2.1.
CREATE XML SCHEMA COLLECTION MiEsquemaEnvio AS
N'<schema xmlns="http://www.w3.org/2001/XMLSchema" >
<element name="Clientes">
<complexType>
<sequence>
<element name="idCliente" type="int" />
<element name="Nombre" type="string"/>
</sequence>
</complexType>
</element>
</schema>
'
GO
CREATE XML SCHEMA COLLECTION MiEsquemaRecepcion AS
<element name="CreditoConcedido" type="decimal"/>
Creando Tipos de mensajes basados en esos esquemas
CREATE MESSAGE TYPE [Envio] VALIDATION= VALID_XML
WITH SCHEMA COLLECTION MiEsquemaEnvio;
CREATE MESSAGE TYPE [Recepcion]
VALIDATION=VALID_XML
WITH SCHEMA COLLECTION MiEsquemaRecepcion;
Creando contratos que permitan enviar y recibir mensajes de este tipo
CREATE CONTRACT [PeticionCredito]
([Envio] SENT BY INITIATOR,[Recepcion] SENT BY TARGET)
Creando las colas para soportar estas cosas
CREATE QUEUE Peticion WITH STATUS=ON;
CREATE QUEUE Respuesta WITH STATUS=ON;
Creando servicios que usen estas colas
CREATE SERVICE SrvPeticion ON
QUEUE [Peticion] ( PeticionCredito);
CREATE SERVICE SrvRespuesta ON
QUEUE [Respuesta] ( PeticionCredito);
Enviando mensajes basados en esos servicios
DECLARE @Cliente xml(MiEsquemaEnvio)
DECLARE @message_type_name NVARCHAR(256)
DECLARE @conversationhandle UNIQUEIDENTIFIER
DECLARE @Conversacion TABLE(
service_instance_id UNIQUEIDENTIFIER,
handle UNIQUEIDENTIFIER,
message_sequence_number BIGINT,
service_name NVARCHAR(512),
service_contract_name NVARCHAR(256),
message_type_name NVARCHAR(256),
validation NCHAR,
message_body VARBINARY(MAX)) ;
Set @cliente=
CAST(N'<Clientes>
<idCliente>10</idCliente>
<Nombre>Miguel Egea (Petición 1)</Nombre>
</Clientes>' as xml(MiEsquemaEnvio))
BEGIN TRANSACTION
BEGIN DIALOG @conversationhandle
FROM SERVICE SrvPeticion
TO SERVICE 'SrvRespuesta'
ON CONTRACT PeticionCredito
WITH ENCRYPTION=OFF;
SEND ON CONVERSATION @conversationhandle
MESSAGE TYPE Envio (@cliente)
COMMIT
Una vez que hemos enviado el mensaje, veamos como recibirlo en el destino.
Declare @conversationhandle uniqueidentifier
declare @saldoCliente as xml(MiEsquemaRecepcion)
Declare @id int
WAITFOR
RECEIVE TOP (1)
conversation_group_id,
conversation_handle,
message_sequence_number,
service_name,
service_contract_name,
message_type_name,
validation,
message_body
FROM Respuesta
INTO @Conversacion
);
SELECT @conversationhandle=handle,
@cliente=message_body
FROM @Conversacion
Tenemos el mensaje, procesarlo ahora pertenece al proceso de negocio, vamos a usar el método value para leer el XML simplificando este proceso para centrarnos en el envio y tratamiento.
set @id= @cliente.value('(/Clientes/idCliente)[1]', 'int' )
SET @SaldoCliente=
<idCliente>' + CAST(@id AS NVARCHAR(10))
+'</idCliente>
<CreditoConcedido>1000.36</CreditoConcedido>
</Clientes>' as xml(MiEsquemaRecepcion));
MESSAGE TYPE Recepcion(@SaldoCliente)
END CONVERSATION @conversationHandle;
El que envió la petición ahora recibe la respuesta y la procesa como estime oportuno
WHILE (1=1)
BEGIN
RECEIVE TOP(1)
FROM Peticion
WHERE conversation_handle = @ConversationHandle
SELECT CAST(Message_body as XML) FROM @CONVERSACION
SELECT @message_type_name=message_type_name
FROM @CONVERSACION
IF @message_type_name =
'http://schemas.microsoft.com/SQL/ServiceBroker/EndDialog'
OR @message_type_name =
'http://schemas.microsoft.com/SQL/ServiceBroker/Error'
select 'acabo'
END CONVERSATION @ConversationHandle ;
BREAK;
END
Esto es un ejemplo de envio y recepción de mensajes mediante Service Broker, aunque hayamos puesto bucles infinitos y waitfors, no entendamos esto como una espera activa ni muchísimo menos, El tipo de aplicaciones que se desarrollen y su complejidad dependrá muchísimo de los requisitos de negocio, SB sin embargo es una plataforma robusta estable, escalable y muy fácilmente configurable que puede permitir hacer aplicaciones asíncronas fácilmente.