Showing posts with label queue. Show all posts
Showing posts with label queue. Show all posts

Saturday, February 25, 2012

messages stuck in sys.transmission_queue

Sorry for the stupid question, but I can't seem to figure it out...

There are 119 messages that are stuck in the transmission queue, all for the same queue. When I check the status of the queue (via sys.service_queues), is_receive_enabled = 1, is_activation_enabled = 1, and max_readers = 3. When I check to see if there is an active queue monitor (via sys.dm_broker_queue_monitors) there is nobody watching this queue. What would cause this queue to be active, enabled but have nobody montioring it? Is there something internal that went wrong that made these (outbound) messages get stuck in the transmission queue, and is not showing up in the views? How can I get these messages "un-stuck" and flow through the system?

A problem I am seeing is the return message to this queue (to signify the target has consumed the message, and to end the conversation) are not being consumed, thus getting stuck in the "DI" state.

Any suggestions would be greatly appreciated.

Thanks in advance,

John Hennesey

p.s. The transmission status is blank for all 119 rows.|||

Are all messages in transmission queue on the same dialog or on different dialogs?
Are the messages remote or local (if local, is it same instance or same db) ?
Attaching the profiler and monitoring for events in the Broker category shows any activity?
Is there any route for the messages destination service in the database?
Do new messages sent end up in the same situation or they get trough fine?

To trigger an internal 'recycle' of the whole broker 'machinery' you can disable and then enable back the broker (ALTER DATABASE ... SET DISABLE_BROKER / ENABLE_BROKER), but I'd like you to try the profiler first to confirm if there realy isn't any broker activity for those messages.

HTH,
~ Remus

|||

Remus - thank you so much for your quick response. I was hoping you would see this... :) To answer your questions:

Are all messages in transmission queue on the same dialog or on different dialogs?

When you say dialog, do you mean the same conversation? The conversation handles are indeed different.|||

I am puzzled myself. My recommendation would be to focus on one individual conversation that exposes the problem. Lookup the conversation_handle in sys.transmission_queue for any of the messages stuck (pick one). Starthing from this, investigate as follows:
- find the corresponding conversation (that owns the message) in sys.conversation_handles
- using the conversation_id, find the peer conversation handle (initiator and target both share the same conversation_id value)
- what states are the two conversation endpoints found in the previous step? For messages to travel, both should be in CONVERSING state.
- check if there are discrepancies between the send_sequence and receive_sequence between the two conversation endpoints. In each direction (initiator to target and target to initiator) there should be a contigous sequence of message numbers: i.e. if initiator's send_sequence is 10 and target's receive_sequence is 5, the messages numbered 5,6..10 should all be in the transmission_queue. See if you can spot any gap (e.g. send_sequence 10, peer's receive_sequence is 9, but message 10 is missing from transmission_queue) or overlap (e.g. send_sequence 10, receive_sequence also 10 but message 10 was not yet deleted from transmission_queue)
- monitor again the Profiler broker events, but filter the events only for the conversation you're focusing on. The meaning of each column displayed in the Profiler for broker events is documented here: http://msdn2.microsoft.com/en-us/library/ms186347.aspx and you can filter based on a given conversation_id (the one you're focusing on).

HTH,
~ Remus

|||

Remus - thank you very much for the response. Today we had to deactivate our queues (for maintenance purposes), and I jumped at the chance to also deactivate the queue in question. Turns out we have a script that deactivates the queues every morning, kicks off a cube processing event (so it will be built on static data), then reactivates the queues. I didn't know it, but this queue is not part of that script. I think this script was the culprit - somehow when things were processing, it severed something, somewhere.

It made it look like the queue was enabled and active, all signs pointed to everything alive and well, but nothing was monitoring the queue (via sys.dm_broker_queue_monitors). We deactivated the queue, disabled the queue, enabled the queue and reactivated the queue and everything started flowing smoothly. Queue counts are going down, our conversations are closing properly and the sys.conversation_endpoints view is showing CD conversations being purged after the 30 minute period. Awesome!

I still don't know exactly what caused it, nor did I get the chance to really dive into your info from the last post, but some of the thing you mentioned got me thinking down this path. I really appreciate your help!

If there are any questions you have from me, please do not hesitate to ask - i.e. if the product group is interested in some of the processes we do that may have caused the queue to be in this state. Otherwise, I will mark this as answer.

Thanks again - have a great weekend.

John

|||

My recommendation would be to describe this problem at http://connect.microsoft.com/SQLServer/Feedback

Thanks,
~ Remus

Messages stopped appearing in Queue!

I recently restored my database from a backup and it seems that something in my service broker setup has stopped working, no messages now appear.

I checked that the broker was enabled (it wasnt and i had to use NEW_BROKER because of the 'same id' message)

The database is still set to trustyworthy.

There are also no messages in sys.transmission_queue

I used profiler with all the broker events enabled and the result was as follows:

Broker:Conversation Group
Broker:Conversation STARTED_OUTBOUND

Broker:Conversation CONVERSING

Broker:Message Classify
Broker:Conversation CLOSED
Broker:Conversation Group
Broker:Message Classify

But i'm not sure whether this highlights a problem or not? Any help gratefully appreciated!!

Thanks,

Andy

Hi,

I had the complete conversation - including the end of the conversation - in a stored procedure.

This was the reason i wasn't getting anything in sys.transmission_queue - i didnt end the conversation and the error appeared.

It turned out to be a permissions thing as when i'd restored the database it had set the owner to [SA]

Sorry for wasting your time if you'd bothered to read my problem!

Cheers,

Andy

Messages stopped appearing in Queue!

I recently restored my database from a backup and it seems that something in my service broker setup has stopped working, no messages now appear.

I checked that the broker was enabled (it wasnt and i had to use NEW_BROKER because of the 'same id' message)

The database is still set to trustyworthy.

There are also no messages in sys.transmission_queue

I used profiler with all the broker events enabled and the result was as follows:

Broker:Conversation Group
Broker:Conversation STARTED_OUTBOUND

Broker:Conversation CONVERSING

Broker:Message Classify
Broker:Conversation CLOSED
Broker:Conversation Group
Broker:Message Classify

But i'm not sure whether this highlights a problem or not? Any help gratefully appreciated!!

Thanks,

Andy

Hi,

I had the complete conversation - including the end of the conversation - in a stored procedure.

This was the reason i wasn't getting anything in sys.transmission_queue - i didnt end the conversation and the error appeared.

It turned out to be a permissions thing as when i'd restored the database it had set the owner to [SA]

Sorry for wasting your time if you'd bothered to read my problem!

Cheers,

Andy

Messages in the sys.transmission_queue for a disable queue

I may have a misunderstanding of how SB works, but this seems like a problem.

If a queue is disable (i.e. status = off) and a message is sent to the queue the message is placed on the sys.transmission_queue. Once the queue is enabled I thought the messages were sent to the queue in the order they were placed on the sys.tranmission_queue? I have been troubleshooting a problem and this is not the case. Do I have a misunderstanding of how the sys.transmission_queue works?

The queue has retention turned off.

Messages are delivered in order within each conversation (RECEIVE cannot return msg 2 before msg 1 for any conversation). But the order of messages in the xmit queue does not determine in any way the order of which messages are actually being delivered.

HTH,
~ Remus

|||

If you have a scenario where you want to send a message to a service broker queue that updates a row in a table and then later you would like to send another message to do another update to the row in the same table and the queue is disabled before the first send there is no way to guarantee these messages will be processed in order they were sent? It sounds like unless you actually end up on the queue itself there is no gurantee in what order the xmit queue will deliver them to the queue. Am I correct?

Thanks for the help

|||

If the order matters, you must deliver them using the same conversation. Otherwise you are never quaranteed anything about the order and you can hit the xmit queue for other reasons that target queue disabled (low memory, a lock bounce etc)

messages aren't getting through after backup / restore on a different server...

after restoring a database and regenerating keys, I'm trying to queue messages, and they're all hanging out in sys.transmission_queue with the following message:
An exception occurred while enqueueing a message in the target queue. Error: 15517, State: 1. Cannot execute as the database principal because the principal "dbo" does not exist, this type of principal cannot be impersonated, or you do not have permission.

I can't find any documentation or blog info on this error... Help!

thanks!Have you set your database to trustworty?

ALTER DATABASE db_name
SET TRUSTWORTHY ON

Also, maje sure you have a master key in both databases.

CREATE DATABASE MASTER KEY
ENCRYPTION BY PASSWORD = 'somePassW0rd1'

Please let us know if this helps

Niels|||hi Niels.

Nope, the SET TRUSTWORTHY ON on the database did not work.

It would probably be helpful if I mentioned that the backup was taken on the April CTP server, and the restore on the September version...

also - both the initiator and target queues live in the same database...

|||

Which server principal (i.e. login) owns the restored database? Has anything changed with the SQL instance or Windows users since backup was taken? For example you are trying to restore on a machine not connected to a domain and the server principal owning the database was a domain user?

Later,
Rushi

|||Rushi -- a domain administrator owns both databases.
Both servers are connected to the domain, and all services are also run by the domain administrator.|||Probably the dbo of the database is the original login that created the database, on the original server, and that login cannot be impersonated on the new server (e.g. the login is the Windows login corresponding to the original server Administrator account).
Use ALTER AUTHORIZATION ON DATABASE <dbname> TO <loginname> to change the owner of the database to a new login (e.g. [sa]), it will change the dbo to map to a login than is OK to be impersonated.

HTH,
~ Remus|||thanks Remus -- that solved the problem.

Message Retieval

Hello again,

A.
This time I would like to get your input on two ways of getting a message off a queue. Both are samples, but I would like to know more about the implications.
This first example (BOL) goes directly to the queue:

WAITFOR (

RECEIVE TOP(1)

@.messageTypeName = message_type_name,

@.messageBody = message_body,

@.conversationHandle = conversation_handle

FROM ExpenseQueue

), TIMEOUT 500 ;
The second one (SQL Server samples) obtains a conversation hanle, then gets a message:
WAITFOR(
GET CONVERSATION GROUP @.conversation_group_id FROM [dbo].[ProcessBCHQueue]),
TIMEOUT 500 ;

RECEIVE
TOP(1)
@.conversation_handle = conversation_handle,
@.message_type_name = message_type_name,
@.message_body =
CASE
WHEN validation = 'X' THEN CAST(message_body AS XML)
ELSE CAST(N'<none/>' AS XML)
END
FROM [dbo].[ProcessBCHQueue]
WHERE conversation_group_id = @.conversation_group_id ;

what are the implications between both calls?
I would think that:
1. In any case messages are initially send via a dialogue, so I am not sure why the first example eliminates the conversation handle;
2. Does the second example allow for more readers getting messages on different conversations, since unique conversation handles are explictly obtained?
3. Since the first method was in the Handling Poison Messages of BOL, is that a more straight forward approach that allows for easier handling of error messages?
4. Anything else that might be interesting to note? Please share.

Thanks again,

Lubomir

The second example shows how to process messages when you need to retrieve a state from your database associated with the incomming messages. The recomended way is to store this state in a table and use the conversation_group as the table key. The second example allows you to first lock an available conversation group (one that has messages to be received), then look up the state associated with this particular group, then receive the messages of this group.

The different approach is only a performance optimization. The first example would require you to look up this state for each message received. The second example allows you to look up the state once, then process all messages for that particular conversation group in a loop, w/o looking up the state again.

The typical example of processing in the second case is:

BEGIN TRANSACTION
WAITFOR (GET CONVERSATION GROUP...), TIMEOUT ...
WHILE (@.conversation_group IS NOT NULL)
BEGIN
-- lookup state in the state table here, using the @.conversation_group key
--
RECEIVE TOP(1) ... WHERE conversation_group = @.conversation_group
WHILE (@.conversation_handle IS NOT NULL)
BEGIN
-- proces message here
--
RECEIVE TOP(1) ... WHERE conversation_group = @.conversation_group
END
COMMIT;
BEGIN TRANSACTION;
WAITFOR (GET CONVERSATION GROUP...), TIMEOUT ...
END
COMMIT

The transaction boundaries are important in this example. One shouldn't commit each individual message as it processes the inner loop, as a commit will actually release the lock on the conversation_group and another reader might alter the looked up state.

There is no difference between the two approaches on how many readers can progress in paralel. Both approaches will lock the conversations in the same way, the difference is only in how the procedure would handle an application specific state lookup.

HTH,
~ Remus

|||Thank you very much Remus,

Lubomir

message queues

I having a fight with what I think is the message queue system when
running stored procedures. If I have this as a sp
print 'Handling First File'
(do some processing on the first file)
print 'Handling Second File'
(do some processing on the second file)
print 'Handling Third File'
(do some processing on the third file)
print 'Done'
I want to use the SQLMDO 'ExecuteWithResultsAndMessages' and
'ServerMessage' functions to use print commands as part of my front end
but what happens is that while all the processing is done my dialog
filled by 'ServerMessage.Message' is blank and then all my print
commands come together - London bus style. (Query Analyser does the
same).
This presumably is down to Message Queuing ? One help file I saw says
something like "when you create a Stored Procedure (with queuing
enabled)...." suggesting that you can create a sp with queing
disabled? but I cant find anything in the syntax to stipulate that.
Is there a way round this so that messages are forwarded by the agent
as they are reached in the script and not queued.?
Thanks
GlennIt really has nothing to do with queuing per say it is that the packet does
not get sent to the client until the batch is done or the buffer is full.
In a nutshell since the packets are around 4K in size it doesn't waste many
round trips each time a little bit of info is placed in the buffer. It
waits until it is full until it sends it or when the batch is done. Here is
an example to show this. Comment out the replicate statement and you will
see it doesn't print until the batch is done.
DECLARE @.X INT
SET @.X = 1
WHILE @.X < 100
BEGIN
PRINT CAST(@.X AS VARCHAR(20))
PRINT REPLICATE(' ',8000)
SET @.X = @.X + 1
waitfor delay '00:00:01'
END
Andrew J. Kelly SQL MVP
<glenn.hughes@.luk.net> wrote in message
news:1140543654.666118.191320@.g44g2000cwa.googlegroups.com...
>I having a fight with what I think is the message queue system when
> running stored procedures. If I have this as a sp
> print 'Handling First File'
> (do some processing on the first file)
> print 'Handling Second File'
> (do some processing on the second file)
> print 'Handling Third File'
> (do some processing on the third file)
> print 'Done'
> I want to use the SQLMDO 'ExecuteWithResultsAndMessages' and
> 'ServerMessage' functions to use print commands as part of my front end
> but what happens is that while all the processing is done my dialog
> filled by 'ServerMessage.Message' is blank and then all my print
> commands come together - London bus style. (Query Analyser does the
> same).
> This presumably is down to Message Queuing ? One help file I saw says
> something like "when you create a Stored Procedure (with queuing
> enabled)...." suggesting that you can create a sp with queing
> disabled? but I cant find anything in the syntax to stipulate that.
> Is there a way round this so that messages are forwarded by the agent
> as they are reached in the script and not queued.?
> Thanks
> Glenn
>|||You can 'cheat' the messages out faster by raising low-level errors...
RAISERROR('Hack!!!',0,1) WITH NOWAIT
HTH,
Ben
"Andrew J. Kelly" <sqlmvpnooospam@.shadhawk.com> wrote in message
news:%23SqYsHxNGHA.1676@.TK2MSFTNGP09.phx.gbl...
> It really has nothing to do with queuing per say it is that the packet
> does not get sent to the client until the batch is done or the buffer is
> full. In a nutshell since the packets are around 4K in size it doesn't
> waste many round trips each time a little bit of info is placed in the
> buffer. It waits until it is full until it sends it or when the batch is
> done. Here is an example to show this. Comment out the replicate
> statement and you will see it doesn't print until the batch is done.
> DECLARE @.X INT
> SET @.X = 1
> WHILE @.X < 100
> BEGIN
> PRINT CAST(@.X AS VARCHAR(20))
> PRINT REPLICATE(' ',8000)
> SET @.X = @.X + 1
> waitfor delay '00:00:01'
> END
>
> --
> Andrew J. Kelly SQL MVP
>
> <glenn.hughes@.luk.net> wrote in message
> news:1140543654.666118.191320@.g44g2000cwa.googlegroups.com...
>|||Thanks to both of you. Ben, I just love that word "Cheat" its what
programming is all about. The error level idea sounds good. I'll try
that
Cheers
Glenn

Message Queue Task 64 bit Cluster issue

Hello,

I'm using the Message Queuing task to create a local private queue message. Everything works great on a 32 bit machine. When I try this on a 64 bit Itanium Cluster I keep getting the message "Message queue service is not available" in my SSIS log. I've using this string as my path "ClusterName\private$\QueueName". Does anyone know of any issues with the Message Queue task on 64 bit or a cluster? The Message Queue service is up and running, it doesn't make sense.

Thanks,

Andy

I found out that you must install MSMS on each node of the cluster separately. Then set up your Message Queue using the Cluster Administrator. See this document for help.

http://download.microsoft.com/download/4/f/5/4f518f76-c1ce-431b-b79f-71caf9e27578/MSMQ3incluster.doc

Also, it's easier if you use the utility mmcv.exe to set up the cluster:

http://support.microsoft.com/?kbid=898701&SD=tech

Andy

Message Queue Task

Ok, im making some progress. So what i have is a Message Queue Task which is bound to a message queue connection manager (which 'tests' ok). The Message Queue Task is set to recieve, variable from string message (declared a variable of type string) and to remove the message from the queue. The output of that task is piped into the data flow task.
The data flow task expands into a XML Source which is configured to get its input from the string i declared in the Message Queue Task and i point the schemas path to an appropriate schema. I then pipe the output of that into a SQL server destination which ive mapped all the columns from the XML message to a table (which the SQL server destination created for me).

It all looks good on paper, and builds properly with no errors etc. There is already a message in the appropriate private queue. When i go to debug it, it just sits on the Message Queue Task node (its yellow) and goes no further. No data is put into the DB. I have put a watcher on the link between the XML Source and the SQL server destination, and can see no data being piped through.
Even if i send another message, the execution of my package doesnt step passed the Message Queue Task. Its just sitting there waiting for something? what? I thought it would block until there was a message on that queue, and then process it if and when it arrives. But it doesnt seem to do that.

Any ideas?

I read on MSDN that you need integration services installed. I have checked and i do, and its running. Is theres something else i need to configure?

Help!

Hi

This works for me on either private or public Message Queue. How did you send the message to the private message queue?

This is what I'm doing

Create a MSMQ task (MSMQ Connection to machinename\private$\juantest1). Create a string variable in the package: sendVariable (value: ValueSend). In The MSMQ Task use the above connection, select send variable and use the create variable. Execute the package

Create another package MSMQReceive (same connection manager). Create a string variable recVariable (value: Default value). In the MSMQ Task select the correct MSMQ connection and for message select Receive Message, message type= variable message; variable = user::recVariable. Put a break point after execution. Execute the package. The value of variable recVariable = ValueSend

Juan Acosta (Microsoft SSIS Team)

This posting is provided "AS IS" with no warranties, and confers no rights

|||Hi Juan, thanks for the reply. Its interesting you ask 'how am i sending it?' I wouldnt have thought it would matter. An MSMQ message should be independant of how it was sent, shouldnt it? Im actaully sending it from a small console .NET 1.1 C# app using the standard .NET MQ library (system.messaging?) Its just a simple XML message. I can post the console app code if you think that would help?
I could also build the sender app in SSIS and see if that works for me. If it does we know its something with the way im sending the message - but that seems a bit counter-intuitve to me.

Thanks again, will let you know how i get on.|||Hi Juan. I have just made another SSIS package which is a simple MSMQ task which is set to send to the private queue i have set up withe the Message Queue Connection Manager (which tested ok). That package runs and says it completed fine, and it posts a message to the private queue (.\private$\testq). I can see the message from the computer managment applet etc.

I run the reciever app and it just sits there doing nothing. Waiting on the MSMQ task.
The way i have it set up is on controlflow tab i have an MSMQ task which pipes into a Dataflow task. i have a break point set on the dataflow task node on the controlflow tab. It never hits that breakpoint, no matter how i sent the message (from my console app or from another SSIS package), whether theres a message there or not when i start the reciever app.

Another thing which MAY be of interest is that im running all this on a virtual PC (WMWare 5.0) running W2K SP4. I have not applied Yukon SP1 yet either.

Still nothing seems to work|||have applied SQLSvr2005 SP 1 now, and it has made no difference :(|||We dont need to install MSMQ triggers do we?|||

Taurineman,

I was just having the same problem assisting a Microsoft Partner. But I found the solution. The message label is what the Message Queue task looks at for the type of message.
For a String Message set the label to "String Message" for a data file set the message label to "Data File Message"

This isn't very straight forward. The way I stumbled onto this is by setting up two Message Queue tasks in my SSIS package. The first one sends the message and the second one recieves the message. This runs just fine. I then I took a look at the messages to determine what I was missing from the messages I was sending from a C# project. It turns out the Label string needs to be exact.

Code To Send Message Correctly with C# project for Message Queue Task to process:
System.Messaging.Message recoverableMessage = new System.Messaging.Message()
recoverableMessage.Body = "Test";
recoverableMessage.Label = "String Message";
recoverableMessage.Recoverable = true;
MessageQueue msgQ = new MessageQueue(@."machinename\private$\810");
msgQ.Send(recoverableMessage);

|||

Unfortunately this forum does not have much discussion on using Message Queue Task.

I tried the above post by Oliver and it worked fine. I have a complex problem in using MSMQ task.

i have a sender package that has a MSMQ task and SQL Exec task. The SQL Exec task get data from SQL 2005 (like "select name from person"). And I used a variable (of type Object) "srcVariable" to store the full result set. I then use MSMQ to send this object to a local private queue. It worked fine. Note that since i used ADO.NET provider, so the actual data type for this object is "System.Data.DataSet". OLEDB provider does NOT work for MSMQ because the object is of type __ComObject that can NOT be serializable.

Next I have another receiver package that has a MSMQ task. The MSMQ task was able to read object from the queue. I use a package-level variable to store it. However, the returning type for this object is "String" but the value is "System.Data.DataSet".

Can any expert please suggest how to convert this object from String type to DataSet type so that it can be used downstream?

|||

So if I understand the objective, it is to store a dataset in MSMQ, and then to retrieve the same dataset in a separate IS package for downstream use.

SSIS will not serialize the the Object ("srcVariable") which contains the DataSet for you. Because of that, when your receiver task picks up the message, all you have is what amounts to the ToString() call on a DataSet, which returns "System.Data.DataSet".

For example, it would be the same in powershell to do the following:

(new-object System.Data.DataSet).ToString()
"System.Data.DataSet"

Instead, you can serialize the DataSet object instance to an SSIS String variable in the sender, and then reconstitute it back from a string to a DataSet in the receiver. For example, if you have in sending package two SSIS variables (an Object named "DataSet" which contains a DataSet and a String named "SerializedDataSet"), and in the receiving package the same two variables, you could use the following script tasks to handle the serialization/de-serialization of the dataset. The DataSet could then be used downstream, perhaps in foreach loop container or a dataflow task.

The first task is used in the sender to serialize the dataset to a string prior to that string's transmission via a MSMQ task. The second is for use in the receiver package after the MSMQ message receipt to de-serialize the stringified dataset for downstream use.

Imports System
Imports System.Data
Imports System.Math
Imports Microsoft.SqlServer.Dts.Runtime
Imports System.IO
Imports System.Text

Public Class ScriptMain

Private shouldTerminate As Boolean = False

Private sourceObject As Object

Private sourceDataSet As DataSet

Private stringifiedDataSet As StringBuilder = New StringBuilder()

Public Sub Main()

Dts.TaskResult = Dts.Results.Success

Try

sourceObject = Dts.Variables("DataSet").Value

sourceDataSet = DirectCast(sourceObject, DataSet)

Using sw As StringWriter = New StringWriter(stringifiedDataSet)

sourceDataSet.WriteXml(sw, XmlWriteMode.WriteSchema)

' stringify DataSet for transmission

End Using

Dts.Variables("SerializedDataSet").Value = _

stringifiedDataSet.ToString()

Catch ex As Exception

shouldTerminate = Dts.Events.FireError(1, _

ex.TargetSite.ToString(), ex.Message, String.Empty, 0)

Dts.TaskResult = Dts.Results.Failure

End Try

End Sub

End Class

Imports System

Imports System.Data

Imports System.Math

Imports Microsoft.SqlServer.Dts.Runtime

Imports System.IO

Imports System.Text

Public Class ScriptMain

Private shouldTerminate As Boolean = False

Private sourceObject As Object

Private stringifiedDataSet As String

Private targetDataSet As DataSet = New DataSet()

Public Sub Main()

Dts.TaskResult = Dts.Results.Success

Try

sourceObject = Dts.Variables("SerializedDataSet").Value

stringifiedDataSet = DirectCast(sourceObject, String)

Using sr As StringReader = New StringReader(stringifiedDataSet)

targetDataSet.ReadXml(sr, XmlReadMode.ReadSchema)

' reconstitute dataset

End Using

Dts.Variables("DataSet").Value = targetDataSet

Catch ex As Exception

shouldTerminate = Dts.Events.FireError(1, _

ex.TargetSite.ToString(), ex.Message, String.Empty, 0)

Dts.TaskResult = Dts.Results.Failure

End Try

End Sub

End Class

|||

This sounds a very plausible solution. I will try it out and post my finding back.

Just out of my curiosity, how do you know that SSIS does not serialize DataSet object while it is sent to Q ? Any documentation info ?

In the MSMQ receiving task, there is a type of "String To Variable"... then what does this really mean ? Does this reconstruct object from a serialized XML string?

|||SSIS does serialize the DataSet stored in the IS Object variable, along with other IS variable types (using a SOAP formatter as you noted in another thread), when using the message type of "Variable Message". The MSMQ task in receive mode just doesn't understand its own sent messages, excepting strings. That is, the MSMQ task is incompatible with itself, when used to send and then receive a non-string variable message type.

Hence the need, at least right now, to use IS String variables (or IS Object variables which can wrap strings), when using the MSMQ task to receive a variable message.

To my knowledge, the "inability to deserialize" non-strings is not documented, as the receive side of the MSMQ task doesn't limit you to variables of type String or Object, when in receive variables mode.|||

This is really good stuff...

Unfortunately i cannot make it work by using the script above.. Did I miss anything ? Here is what I did.

1. Inside sender package, I used your sending script above, and was able to send to Q using "String message" as Message Type. Inside StringMessage column, I keyed in "User::SerializedDataSet". This works fine and the message got sent into the Q.

2. Inside receiver package, I have a receiving MSMQ task which is followed by a script task (that is copied and pasted your above receiving script). For MSMQ task, in the "Receive" property page, i configured MessageType to be "String message to variable" and variable to be "User::SerializedDataSet". And this MSMQ task works fine. BUT, the script task blows up at:

targetDataSet.ReadXml(sr, XmlReadMode.ReadSchema)

Anything is wrong here? Please help.

BTW - I also tried String Message (as opposed to "String message to variable") for MessageType inside receiver package and did not get it work either.


|||

Steve Wang 2006 wrote:

This is really good stuff...

Unfortunately i cannot make it work by using the script above.. Did I miss anything ? Here is what I did.

1. Inside sender package, I used your sending script above, and was able to send to Q using "String message" as Message Type. Inside StringMessage column, I keyed in "User::SerializedDataSet". This works fine and the message got sent into the Q.

Set the expression on the Message String property of the sending MSMQ task to the IS string variable User::SerializedDataSet. That is, the expressions node for the task should look like:
MessageString => @.[User::SerializedDataSet]
This as opposed to the literal value of "User::SerializedDataSet" in the StringMessage property.

2. Inside receiver package, I have a receiving MSMQ task which is followed by a script task (that is copied and pasted your above receiving script). For MSMQ task, in the "Receive" property page, i configured MessageType to be "String message to variable" and variable to be "User::SerializedDataSet". And this MSMQ task works fine. BUT, the script task blows up at:

targetDataSet.ReadXml(sr, XmlReadMode.ReadSchema)

Anything is wrong here? Please help.

The "blow up" on the .ReadXml line is a consequence of the message not containly xml (yet). As long as the message does not contain xml, this DataSet.ReadXml() method will throw an exception. So fixing the sending package to use an expression containing xml for the task's StringMessage property will "fix" the receiver task too.

BTW - I also tried String Message (as opposed to "String message to variable") for MessageType inside receiver package and did not get it work either.

The MessageType property inside the receive task should be set to "String Message to Variable", loading the message contents into the receiver package's IS string variable User::SerializedDataSet.

|||

Thank you much... Both Sender package and receiver packages worked great.

I also tried to send a DataSet object from C# code to the same Q, it worked as well. Here is what I did...for reference purpose.

Inside C# code, get data from database and create a DataSet object. Then use the serilization above to create an XML string which is sent to the Q next. Some tricky stuff here is: Be sure to use the identical lable as noted above AND approrpiate formatter which is ActiveXMessageFormatter for the message. I spent quite a bit time to figure this out. I am assuming that SSIS uses this formatter but I did not find any documentation on this. Otherwise SSIS's MSMQ Receiving task won't work.

Of course once SSIS MSMQ Receiving task reads the string, it needs to convert to DataSet as jaegd pointed out above.

|||

As an extra mile to go....

i tried inside C# code to receive the message from Q that is sent from SSIS MSMQ sender package... and I was not able to get the message by using "ActiveXMessageFormatter" which was applied to the Q instance. It blows up at Receive() method call by throwing the following error:

"cannot deserialize the message passed as an argument. Cannot recognize the serialization format"

Any suggenstion ?

Message Queue Task

Ok, im making some progress. So what i have is a Message Queue Task which is bound to a message queue connection manager (which 'tests' ok). The Message Queue Task is set to recieve, variable from string message (declared a variable of type string) and to remove the message from the queue. The output of that task is piped into the data flow task.
The data flow task expands into a XML Source which is configured to get its input from the string i declared in the Message Queue Task and i point the schemas path to an appropriate schema. I then pipe the output of that into a SQL server destination which ive mapped all the columns from the XML message to a table (which the SQL server destination created for me).

It all looks good on paper, and builds properly with no errors etc. There is already a message in the appropriate private queue. When i go to debug it, it just sits on the Message Queue Task node (its yellow) and goes no further. No data is put into the DB. I have put a watcher on the link between the XML Source and the SQL server destination, and can see no data being piped through.
Even if i send another message, the execution of my package doesnt step passed the Message Queue Task. Its just sitting there waiting for something? what? I thought it would block until there was a message on that queue, and then process it if and when it arrives. But it doesnt seem to do that.

Any ideas?

I read on MSDN that you need integration services installed. I have checked and i do, and its running. Is theres something else i need to configure?

Help!

Hi

This works for me on either private or public Message Queue. How did you send the message to the private message queue?

This is what I'm doing

Create a MSMQ task (MSMQ Connection to machinename\private$\juantest1). Create a string variable in the package: sendVariable (value: ValueSend). In The MSMQ Task use the above connection, select send variable and use the create variable. Execute the package

Create another package MSMQReceive (same connection manager). Create a string variable recVariable (value: Default value). In the MSMQ Task select the correct MSMQ connection and for message select Receive Message, message type= variable message; variable = user::recVariable. Put a break point after execution. Execute the package. The value of variable recVariable = ValueSend

Juan Acosta (Microsoft SSIS Team)

This posting is provided "AS IS" with no warranties, and confers no rights

|||Hi Juan, thanks for the reply. Its interesting you ask 'how am i sending it?' I wouldnt have thought it would matter. An MSMQ message should be independant of how it was sent, shouldnt it? Im actaully sending it from a small console .NET 1.1 C# app using the standard .NET MQ library (system.messaging?) Its just a simple XML message. I can post the console app code if you think that would help?
I could also build the sender app in SSIS and see if that works for me. If it does we know its something with the way im sending the message - but that seems a bit counter-intuitve to me.

Thanks again, will let you know how i get on.

|||Hi Juan. I have just made another SSIS package which is a simple MSMQ task which is set to send to the private queue i have set up withe the Message Queue Connection Manager (which tested ok). That package runs and says it completed fine, and it posts a message to the private queue (.\private$\testq). I can see the message from the computer managment applet etc.

I run the reciever app and it just sits there doing nothing. Waiting on the MSMQ task.
The way i have it set up is on controlflow tab i have an MSMQ task which pipes into a Dataflow task. i have a break point set on the dataflow task node on the controlflow tab. It never hits that breakpoint, no matter how i sent the message (from my console app or from another SSIS package), whether theres a message there or not when i start the reciever app.

Another thing which MAY be of interest is that im running all this on a virtual PC (WMWare 5.0) running W2K SP4. I have not applied Yukon SP1 yet either.

Still nothing seems to work

|||have applied SQLSvr2005 SP 1 now, and it has made no difference :(
|||We dont need to install MSMQ triggers do we?
|||

Taurineman,

I was just having the same problem assisting a Microsoft Partner. But I found the solution. The message label is what the Message Queue task looks at for the type of message.
For a String Message set the label to "String Message" for a data file set the message label to "Data File Message"

This isn't very straight forward. The way I stumbled onto this is by setting up two Message Queue tasks in my SSIS package. The first one sends the message and the second one recieves the message. This runs just fine. I then I took a look at the messages to determine what I was missing from the messages I was sending from a C# project. It turns out the Label string needs to be exact.

Code To Send Message Correctly with C# project for Message Queue Task to process:
System.Messaging.Message recoverableMessage = new System.Messaging.Message()
recoverableMessage.Body = "Test";
recoverableMessage.Label = "String Message";
recoverableMessage.Recoverable = true;
MessageQueue msgQ = new MessageQueue(@."machinename\private$\810");
msgQ.Send(recoverableMessage);

|||

Unfortunately this forum does not have much discussion on using Message Queue Task.

I tried the above post by Oliver and it worked fine. I have a complex problem in using MSMQ task.

i have a sender package that has a MSMQ task and SQL Exec task. The SQL Exec task get data from SQL 2005 (like "select name from person"). And I used a variable (of type Object) "srcVariable" to store the full result set. I then use MSMQ to send this object to a local private queue. It worked fine. Note that since i used ADO.NET provider, so the actual data type for this object is "System.Data.DataSet". OLEDB provider does NOT work for MSMQ because the object is of type __ComObject that can NOT be serializable.

Next I have another receiver package that has a MSMQ task. The MSMQ task was able to read object from the queue. I use a package-level variable to store it. However, the returning type for this object is "String" but the value is "System.Data.DataSet".

Can any expert please suggest how to convert this object from String type to DataSet type so that it can be used downstream?

|||

So if I understand the objective, it is to store a dataset in MSMQ, and then to retrieve the same dataset in a separate IS package for downstream use.

SSIS will not serialize the the Object ("srcVariable") which contains the DataSet for you. Because of that, when your receiver task picks up the message, all you have is what amounts to the ToString() call on a DataSet, which returns "System.Data.DataSet".

For example, it would be the same in powershell to do the following:

(new-object System.Data.DataSet).ToString()
"System.Data.DataSet"

Instead, you can serialize the DataSet object instance to an SSIS String variable in the sender, and then reconstitute it back from a string to a DataSet in the receiver. For example, if you have in sending package two SSIS variables (an Object named "DataSet" which contains a DataSet and a String named "SerializedDataSet"), and in the receiving package the same two variables, you could use the following script tasks to handle the serialization/de-serialization of the dataset. The DataSet could then be used downstream, perhaps in foreach loop container or a dataflow task.

The first task is used in the sender to serialize the dataset to a string prior to that string's transmission via a MSMQ task. The second is for use in the receiver package after the MSMQ message receipt to de-serialize the stringified dataset for downstream use.

Imports System
Imports System.Data
Imports System.Math
Imports Microsoft.SqlServer.Dts.Runtime
Imports System.IO
Imports System.Text

Public Class ScriptMain

Private shouldTerminate As Boolean = False

Private sourceObject As Object

Private sourceDataSet As DataSet

Private stringifiedDataSet As StringBuilder = New StringBuilder()

Public Sub Main()

Dts.TaskResult = Dts.Results.Success

Try

sourceObject = Dts.Variables("DataSet").Value

sourceDataSet = DirectCast(sourceObject, DataSet)

Using sw As StringWriter = New StringWriter(stringifiedDataSet)

sourceDataSet.WriteXml(sw, XmlWriteMode.WriteSchema)

' stringify DataSet for transmission

End Using

Dts.Variables("SerializedDataSet").Value = _

stringifiedDataSet.ToString()

Catch ex As Exception

shouldTerminate = Dts.Events.FireError(1, _

ex.TargetSite.ToString(), ex.Message, String.Empty, 0)

Dts.TaskResult = Dts.Results.Failure

End Try

End Sub

End Class

Imports System

Imports System.Data

Imports System.Math

Imports Microsoft.SqlServer.Dts.Runtime

Imports System.IO

Imports System.Text

Public Class ScriptMain

Private shouldTerminate As Boolean = False

Private sourceObject As Object

Private stringifiedDataSet As String

Private targetDataSet As DataSet = New DataSet()

Public Sub Main()

Dts.TaskResult = Dts.Results.Success

Try

sourceObject = Dts.Variables("SerializedDataSet").Value

stringifiedDataSet = DirectCast(sourceObject, String)

Using sr As StringReader = New StringReader(stringifiedDataSet)

targetDataSet.ReadXml(sr, XmlReadMode.ReadSchema)

' reconstitute dataset

End Using

Dts.Variables("DataSet").Value = targetDataSet

Catch ex As Exception

shouldTerminate = Dts.Events.FireError(1, _

ex.TargetSite.ToString(), ex.Message, String.Empty, 0)

Dts.TaskResult = Dts.Results.Failure

End Try

End Sub

End Class

|||

This sounds a very plausible solution. I will try it out and post my finding back.

Just out of my curiosity, how do you know that SSIS does not serialize DataSet object while it is sent to Q ? Any documentation info ?

In the MSMQ receiving task, there is a type of "String To Variable"... then what does this really mean ? Does this reconstruct object from a serialized XML string?

|||SSIS does serialize the DataSet stored in the IS Object variable, along with other IS variable types (using a SOAP formatter as you noted in another thread), when using the message type of "Variable Message". The MSMQ task in receive mode just doesn't understand its own sent messages, excepting strings. That is, the MSMQ task is incompatible with itself, when used to send and then receive a non-string variable message type.

Hence the need, at least right now, to use IS String variables (or IS Object variables which can wrap strings), when using the MSMQ task to receive a variable message.

To my knowledge, the "inability to deserialize" non-strings is not documented, as the receive side of the MSMQ task doesn't limit you to variables of type String or Object, when in receive variables mode.
|||

This is really good stuff...

Unfortunately i cannot make it work by using the script above.. Did I miss anything ? Here is what I did.

1. Inside sender package, I used your sending script above, and was able to send to Q using "String message" as Message Type. Inside StringMessage column, I keyed in "User::SerializedDataSet". This works fine and the message got sent into the Q.

2. Inside receiver package, I have a receiving MSMQ task which is followed by a script task (that is copied and pasted your above receiving script). For MSMQ task, in the "Receive" property page, i configured MessageType to be "String message to variable" and variable to be "User::SerializedDataSet". And this MSMQ task works fine. BUT, the script task blows up at:

targetDataSet.ReadXml(sr, XmlReadMode.ReadSchema)

Anything is wrong here? Please help.

BTW - I also tried String Message (as opposed to "String message to variable") for MessageType inside receiver package and did not get it work either.


|||

Steve Wang 2006 wrote:

This is really good stuff...

Unfortunately i cannot make it work by using the script above.. Did I miss anything ? Here is what I did.

1. Inside sender package, I used your sending script above, and was able to send to Q using "String message" as Message Type. Inside StringMessage column, I keyed in "User::SerializedDataSet". This works fine and the message got sent into the Q.

Set the expression on the Message String property of the sending MSMQ task to the IS string variable User::SerializedDataSet. That is, the expressions node for the task should look like:
MessageString => @.[User::SerializedDataSet]
This as opposed to the literal value of "User::SerializedDataSet" in the StringMessage property.

2. Inside receiver package, I have a receiving MSMQ task which is followed by a script task (that is copied and pasted your above receiving script). For MSMQ task, in the "Receive" property page, i configured MessageType to be "String message to variable" and variable to be "User::SerializedDataSet". And this MSMQ task works fine. BUT, the script task blows up at:

targetDataSet.ReadXml(sr, XmlReadMode.ReadSchema)

Anything is wrong here? Please help.

The "blow up" on the .ReadXml line is a consequence of the message not containly xml (yet). As long as the message does not contain xml, this DataSet.ReadXml() method will throw an exception. So fixing the sending package to use an expression containing xml for the task's StringMessage property will "fix" the receiver task too.

BTW - I also tried String Message (as opposed to "String message to variable") for MessageType inside receiver package and did not get it work either.

The MessageType property inside the receive task should be set to "String Message to Variable", loading the message contents into the receiver package's IS string variable User::SerializedDataSet.

|||

Thank you much... Both Sender package and receiver packages worked great.

I also tried to send a DataSet object from C# code to the same Q, it worked as well. Here is what I did...for reference purpose.

Inside C# code, get data from database and create a DataSet object. Then use the serilization above to create an XML string which is sent to the Q next. Some tricky stuff here is: Be sure to use the identical lable as noted above AND approrpiate formatter which is ActiveXMessageFormatter for the message. I spent quite a bit time to figure this out. I am assuming that SSIS uses this formatter but I did not find any documentation on this. Otherwise SSIS's MSMQ Receiving task won't work.

Of course once SSIS MSMQ Receiving task reads the string, it needs to convert to DataSet as jaegd pointed out above.

|||

As an extra mile to go....

i tried inside C# code to receive the message from Q that is sent from SSIS MSMQ sender package... and I was not able to get the message by using "ActiveXMessageFormatter" which was applied to the Q instance. It blows up at Receive() method call by throwing the following error:

"cannot deserialize the message passed as an argument. Cannot recognize the serialization format"

Any suggenstion ?

Message Queue Task

Ok, im making some progress. So what i have is a Message Queue Task which is bound to a message queue connection manager (which 'tests' ok). The Message Queue Task is set to recieve, variable from string message (declared a variable of type string) and to remove the message from the queue. The output of that task is piped into the data flow task.
The data flow task expands into a XML Source which is configured to get its input from the string i declared in the Message Queue Task and i point the schemas path to an appropriate schema. I then pipe the output of that into a SQL server destination which ive mapped all the columns from the XML message to a table (which the SQL server destination created for me).

It all looks good on paper, and builds properly with no errors etc. There is already a message in the appropriate private queue. When i go to debug it, it just sits on the Message Queue Task node (its yellow) and goes no further. No data is put into the DB. I have put a watcher on the link between the XML Source and the SQL server destination, and can see no data being piped through.
Even if i send another message, the execution of my package doesnt step passed the Message Queue Task. Its just sitting there waiting for something? what? I thought it would block until there was a message on that queue, and then process it if and when it arrives. But it doesnt seem to do that.

Any ideas?

I read on MSDN that you need integration services installed. I have checked and i do, and its running. Is theres something else i need to configure?

Help!

Hi

This works for me on either private or public Message Queue. How did you send the message to the private message queue?

This is what I'm doing

Create a MSMQ task (MSMQ Connection to machinename\private$\juantest1). Create a string variable in the package: sendVariable (value: ValueSend). In The MSMQ Task use the above connection, select send variable and use the create variable. Execute the package

Create another package MSMQReceive (same connection manager). Create a string variable recVariable (value: Default value). In the MSMQ Task select the correct MSMQ connection and for message select Receive Message, message type= variable message; variable = user::recVariable. Put a break point after execution. Execute the package. The value of variable recVariable = ValueSend

Juan Acosta (Microsoft SSIS Team)

This posting is provided "AS IS" with no warranties, and confers no rights

|||Hi Juan, thanks for the reply. Its interesting you ask 'how am i sending it?' I wouldnt have thought it would matter. An MSMQ message should be independant of how it was sent, shouldnt it? Im actaully sending it from a small console .NET 1.1 C# app using the standard .NET MQ library (system.messaging?) Its just a simple XML message. I can post the console app code if you think that would help?
I could also build the sender app in SSIS and see if that works for me. If it does we know its something with the way im sending the message - but that seems a bit counter-intuitve to me.

Thanks again, will let you know how i get on.

|||Hi Juan. I have just made another SSIS package which is a simple MSMQ task which is set to send to the private queue i have set up withe the Message Queue Connection Manager (which tested ok). That package runs and says it completed fine, and it posts a message to the private queue (.\private$\testq). I can see the message from the computer managment applet etc.

I run the reciever app and it just sits there doing nothing. Waiting on the MSMQ task.
The way i have it set up is on controlflow tab i have an MSMQ task which pipes into a Dataflow task. i have a break point set on the dataflow task node on the controlflow tab. It never hits that breakpoint, no matter how i sent the message (from my console app or from another SSIS package), whether theres a message there or not when i start the reciever app.

Another thing which MAY be of interest is that im running all this on a virtual PC (WMWare 5.0) running W2K SP4. I have not applied Yukon SP1 yet either.

Still nothing seems to work

|||have applied SQLSvr2005 SP 1 now, and it has made no difference :(
|||We dont need to install MSMQ triggers do we?
|||

Taurineman,

I was just having the same problem assisting a Microsoft Partner. But I found the solution. The message label is what the Message Queue task looks at for the type of message.
For a String Message set the label to "String Message" for a data file set the message label to "Data File Message"

This isn't very straight forward. The way I stumbled onto this is by setting up two Message Queue tasks in my SSIS package. The first one sends the message and the second one recieves the message. This runs just fine. I then I took a look at the messages to determine what I was missing from the messages I was sending from a C# project. It turns out the Label string needs to be exact.

Code To Send Message Correctly with C# project for Message Queue Task to process:
System.Messaging.Message recoverableMessage = new System.Messaging.Message()
recoverableMessage.Body = "Test";
recoverableMessage.Label = "String Message";
recoverableMessage.Recoverable = true;
MessageQueue msgQ = new MessageQueue(@."machinename\private$\810");
msgQ.Send(recoverableMessage);

|||

Unfortunately this forum does not have much discussion on using Message Queue Task.

I tried the above post by Oliver and it worked fine. I have a complex problem in using MSMQ task.

i have a sender package that has a MSMQ task and SQL Exec task. The SQL Exec task get data from SQL 2005 (like "select name from person"). And I used a variable (of type Object) "srcVariable" to store the full result set. I then use MSMQ to send this object to a local private queue. It worked fine. Note that since i used ADO.NET provider, so the actual data type for this object is "System.Data.DataSet". OLEDB provider does NOT work for MSMQ because the object is of type __ComObject that can NOT be serializable.

Next I have another receiver package that has a MSMQ task. The MSMQ task was able to read object from the queue. I use a package-level variable to store it. However, the returning type for this object is "String" but the value is "System.Data.DataSet".

Can any expert please suggest how to convert this object from String type to DataSet type so that it can be used downstream?

|||

So if I understand the objective, it is to store a dataset in MSMQ, and then to retrieve the same dataset in a separate IS package for downstream use.

SSIS will not serialize the the Object ("srcVariable") which contains the DataSet for you. Because of that, when your receiver task picks up the message, all you have is what amounts to the ToString() call on a DataSet, which returns "System.Data.DataSet".

For example, it would be the same in powershell to do the following:

(new-object System.Data.DataSet).ToString()
"System.Data.DataSet"

Instead, you can serialize the DataSet object instance to an SSIS String variable in the sender, and then reconstitute it back from a string to a DataSet in the receiver. For example, if you have in sending package two SSIS variables (an Object named "DataSet" which contains a DataSet and a String named "SerializedDataSet"), and in the receiving package the same two variables, you could use the following script tasks to handle the serialization/de-serialization of the dataset. The DataSet could then be used downstream, perhaps in foreach loop container or a dataflow task.

The first task is used in the sender to serialize the dataset to a string prior to that string's transmission via a MSMQ task. The second is for use in the receiver package after the MSMQ message receipt to de-serialize the stringified dataset for downstream use.

Imports System
Imports System.Data
Imports System.Math
Imports Microsoft.SqlServer.Dts.Runtime
Imports System.IO
Imports System.Text

PublicClass ScriptMain

Private shouldTerminateAsBoolean =False

Private sourceObjectAsObject

Private sourceDataSetAs DataSet

Private stringifiedDataSetAs StringBuilder =New StringBuilder()

PublicSub Main()

Dts.TaskResult = Dts.Results.Success

Try

sourceObject = Dts.Variables("DataSet").Value

sourceDataSet =DirectCast(sourceObject, DataSet)

Using swAs StringWriter =New StringWriter(stringifiedDataSet)

sourceDataSet.WriteXml(sw, XmlWriteMode.WriteSchema)

' stringify DataSet for transmission

EndUsing

Dts.Variables("SerializedDataSet").Value = _

stringifiedDataSet.ToString()

Catch exAs Exception

shouldTerminate = Dts.Events.FireError(1, _

ex.TargetSite.ToString(), ex.Message,String.Empty, 0)

Dts.TaskResult = Dts.Results.Failure

EndTry

EndSub

EndClass

Imports System

Imports System.Data

Imports System.Math

Imports Microsoft.SqlServer.Dts.Runtime

Imports System.IO

Imports System.Text

PublicClass ScriptMain

Private shouldTerminateAsBoolean =False

Private sourceObjectAsObject

Private stringifiedDataSetAsString

Private targetDataSetAs DataSet =New DataSet()

PublicSub Main()

Dts.TaskResult = Dts.Results.Success

Try

sourceObject = Dts.Variables("SerializedDataSet").Value

stringifiedDataSet =DirectCast(sourceObject,String)

Using srAs StringReader =New StringReader(stringifiedDataSet)

targetDataSet.ReadXml(sr, XmlReadMode.ReadSchema)

' reconstitute dataset

EndUsing

Dts.Variables("DataSet").Value = targetDataSet

Catch exAs Exception

shouldTerminate = Dts.Events.FireError(1, _

ex.TargetSite.ToString(), ex.Message,String.Empty, 0)

Dts.TaskResult = Dts.Results.Failure

EndTry

EndSub

EndClass

|||

This sounds a very plausible solution. I will try it out and post my finding back.

Just out of my curiosity, how do you know that SSIS does not serialize DataSet object while it is sent to Q ? Any documentation info ?

In the MSMQ receiving task, there is a type of "String To Variable"... then what does this really mean ? Does this reconstruct object from a serialized XML string?

|||SSIS does serialize the DataSet stored in the IS Object variable, along with other IS variable types (using a SOAP formatter as you noted in another thread), when using the message type of "Variable Message". The MSMQ task in receive mode just doesn't understand its own sent messages, excepting strings. That is, the MSMQ task is incompatible with itself, when used to send and then receive a non-string variable message type.

Hence the need, at least right now, to use IS String variables (or IS Object variables which can wrap strings), when using the MSMQ task to receive a variable message.

To my knowledge, the "inability to deserialize" non-strings is not documented, as the receive side of the MSMQ task doesn't limit you to variables of type String or Object, when in receive variables mode.
|||

This is really good stuff...

Unfortunately i cannot make it work by using the script above.. Did I miss anything ? Here is what I did.

1. Inside sender package, I used your sending script above, and was able to send to Q using "String message" as Message Type. Inside StringMessage column, I keyed in "User::SerializedDataSet". This works fine and the message got sent into the Q.

2. Inside receiver package, I have a receiving MSMQ task which is followed by a script task (that is copied and pasted your above receiving script). For MSMQ task, in the "Receive" property page, i configured MessageType to be "String message to variable" and variable to be "User::SerializedDataSet". And this MSMQ task works fine. BUT, the script task blows up at:

targetDataSet.ReadXml(sr, XmlReadMode.ReadSchema)

Anything is wrong here? Please help.

BTW - I also tried String Message (as opposed to "String message to variable") for MessageType inside receiver package and did not get it work either.


|||

Steve Wang 2006 wrote:

This is really good stuff...

Unfortunately i cannot make it work by using the script above.. Did I miss anything ? Here is what I did.

1. Inside sender package, I used your sending script above, and was able to send to Q using "String message" as Message Type. Inside StringMessage column, I keyed in "User::SerializedDataSet". This works fine and the message got sent into the Q.

Set the expression on the Message String property of the sending MSMQ task to the IS string variable User::SerializedDataSet. That is, the expressions node for the task should look like:
MessageString => @.[User::SerializedDataSet]
This as opposed to the literal value of "User::SerializedDataSet" in the StringMessage property.

2. Inside receiver package, I have a receiving MSMQ task which is followed by a script task (that is copied and pasted your above receiving script). For MSMQ task, in the "Receive" property page, i configured MessageType to be "String message to variable" and variable to be "User::SerializedDataSet". And this MSMQ task works fine. BUT, the script task blows up at:

targetDataSet.ReadXml(sr, XmlReadMode.ReadSchema)

Anything is wrong here? Please help.

The "blow up" on the .ReadXml line is a consequence of the message not containly xml (yet). As long as the message does not contain xml, this DataSet.ReadXml() method will throw an exception. So fixing the sending package to use an expression containing xml for the task's StringMessage property will "fix" the receiver task too.

BTW - I also tried String Message (as opposed to "String message to variable") for MessageType inside receiver package and did not get it work either.

The MessageType property inside the receive task should be set to "String Message to Variable", loading the message contents into the receiver package's IS string variable User::SerializedDataSet.

|||

Thank you much... Both Sender package and receiver packages worked great.

I also tried to send a DataSet object from C# code to the same Q, it worked as well. Here is what I did...for reference purpose.

Inside C# code, get data from database and create a DataSet object. Then use the serilization above to create an XML string which is sent to the Q next. Some tricky stuff here is: Be sure to use the identical lable as noted above AND approrpiate formatter which is ActiveXMessageFormatter for the message. I spent quite a bit time to figure this out. I am assuming that SSIS uses this formatter but I did not find any documentation on this. Otherwise SSIS's MSMQ Receiving task won't work.

Of course once SSIS MSMQ Receiving task reads the string, it needs to convert to DataSet as jaegd pointed out above.

|||

As an extra mile to go....

i tried inside C# code to receive the message from Q that is sent from SSIS MSMQ sender package... and I was not able to get the message by using "ActiveXMessageFormatter" which was applied to the Q instance. It blows up at Receive() method call by throwing the following error:

"cannot deserialize the message passed as an argument. Cannot recognize the serialization format"

Any suggenstion ?

Message Queue Task

Simple Question.

I have a requirement to read XML Messages from a Remote private MSMQ.

These messages are essentially Database records that will need cleaning up and insterting into a Local Database table.

Is this possible with SSIS?

Would Biztalk be a more suitable tool for this type of process?

If its possible, are there any resources taht can point me in the right direction?

Thanks for your help!

J.

That is what the Message Queue task is for, so it seems possible, though I don't have personal experience with using it to read a Remote private queue.

Message Queue

Hi, I have a question, I don't know if it is possible but I have an
application (.NET) that executes queries against SQL Server 2000. I have an
scenario where the database maybe is offline. I have been working with MSMQ
to communicate between apps and send messages from SQL Server but my question
is if SQL Server can read from the queue.
I want to send the query to a queue and when SQL is up again read from the
queue and process the queries, is this possible?
Thanks
Hi
You need to do that in code. SQL Server 2000 does not process against
message queues.
Regards
Mike
"Salvador" wrote:

> Hi, I have a question, I don't know if it is possible but I have an
> application (.NET) that executes queries against SQL Server 2000. I have an
> scenario where the database maybe is offline. I have been working with MSMQ
> to communicate between apps and send messages from SQL Server but my question
> is if SQL Server can read from the queue.
> I want to send the query to a queue and when SQL is up again read from the
> queue and process the queries, is this possible?
> Thanks
>

Message Queue

Hi, I have a question, I don't know if it is possible but I have an
application (.NET) that executes queries against SQL Server 2000. I have an
scenario where the database maybe is offline. I have been working with MSMQ
to communicate between apps and send messages from SQL Server but my question
is if SQL Server can read from the queue.
I want to send the query to a queue and when SQL is up again read from the
queue and process the queries, is this possible?
ThanksHi
You need to do that in code. SQL Server 2000 does not process against
message queues.
Regards
Mike
"Salvador" wrote:
> Hi, I have a question, I don't know if it is possible but I have an
> application (.NET) that executes queries against SQL Server 2000. I have an
> scenario where the database maybe is offline. I have been working with MSMQ
> to communicate between apps and send messages from SQL Server but my question
> is if SQL Server can read from the queue.
> I want to send the query to a queue and when SQL is up again read from the
> queue and process the queries, is this possible?
> Thanks
>

Message Queue

Hi, I have a question, I don't know if it is possible but I have an
application (.NET) that executes queries against SQL Server 2000. I have an
scenario where the database maybe is offline. I have been working with MSMQ
to communicate between apps and send messages from SQL Server but my questio
n
is if SQL Server can read from the queue.
I want to send the query to a queue and when SQL is up again read from the
queue and process the queries, is this possible?
ThanksHi
You need to do that in code. SQL Server 2000 does not process against
message queues.
Regards
Mike
"Salvador" wrote:

> Hi, I have a question, I don't know if it is possible but I have an
> application (.NET) that executes queries against SQL Server 2000. I have a
n
> scenario where the database maybe is offline. I have been working with MSM
Q
> to communicate between apps and send messages from SQL Server but my quest
ion
> is if SQL Server can read from the queue.
> I want to send the query to a queue and when SQL is up again read from the
> queue and process the queries, is this possible?
> Thanks
>

Monday, February 20, 2012

Message Ordering

When I am receiving a batch of message from a queue to process, does it matter if I order by the queuing_order or the message_sequence_number? I want to make sure my messages process in the order in which they were put into the queue, which I know will happen if I process messages one-by-one, but want to make sure that the data I pull and process execute in the order in which they were received.

Tim

Either will do. RECEIVE projects the resultset in the order status, conversation_group, conversation_handle, queueing_order. I'd use the same order in my batch just for consistency (e.g. if the app logic is later moved to a CLR procedure processing a SqlDataReader, the order is unchanged).|||Sounds good, will do.

I did notice something the other day related to batch processing that I think could occur if you are not careful. It may be related to how I am handling the batch...let me know what you think:

I keep a convo open for ~ 90 seconds,or until a new message is sent. When I notice that a convo has gotten too old, I create a new one and process messages on that conversation. When I do this, I send an EndOfStream message that tells my procedures that it is time to end the conversation, and no new messages are sent on that older conversation. The potential problem I see with this is that when I create a new convo and send an EndOfStream message, the new convo starts processing messages right away, even maybe before the EndOfStream message has been processed, and all messages along with that convo processed. This, potentially, could mean that my messages are being processed out of order, which is really something that I can tolerate, but really don't want. Do you think it makes sense to try to add additional logic to prevent this from happening, or is there some other construct, such as a type of conversation lock I could use, to prevent this from happening?
Thanks,
Tim

message lost

Hi...

My service broker was working...all of a sudden it stopped working...so i figured out destination queue was disabled and I set it as

ALTER QUEUE SERVERQUEUE

WITH STATUS = ON, RETENTION = ON, ACTIVATION (

STATUS = ON, PROCEDURE_NAME = usp_OnReceiveMessage,

MAX_QUEUE_READERS = 5, EXECUTE AS OWNER )

Also altered my database for trustworthy after going through some posts previously.

Now the message is sent...i dont see any message in my tranmission queue but i dont receive the message in destination server.

When i checked endpoints...select * from sys.conversation_endpoints I see the last message with st_desc as conversing...

how do I solve this...?

Thanks,

Pramod

The queue must have been disabled because you must have rolled back a transaction that performed a RECEIVE on the queue 5 or more times consecutively. Read about poised message handling here.

If the message is neither in transmission queue nor in the destination queue, chances are that the dialog was errored. Look in the initiator queue as well. I don't get what you mean by "the last message" in sys.conversation_endpoints. The conversation endpoints view does not contain any messages. The st_desc column describes the state of the conversation endpoint.

|||

Rushi:

I reconfigured the service broker...this time...in transmission queue its showing this error....

Connection handshake failed. The certificate used by the peer is invalid due to the following reason: The database principal has no mapping to a server principal.
State 89.

What does this mean ?

Thanks,

|||

You are using certificates for adjacent (i.e. transport) security. The certificate used by the peer belongs to a user in master who is not mapped to a login. This could happen either because:

i) You created a user in master without login.

ii) You created a user in master with a login, but later dropped that login, thus orphaning that user.

The fix would be to create a SQL login, then create a user in master for this login and alter authorization of the peers certificate to be owned by this user. Next grant connection permission on the service broker endpoint to the newly created login.

Hope that helps.

|||

Rushi:

I want to confirm few things here...before proceeding...

Lets take a login sbuser(created to login with sql authentication). This is the login i would be using to create endpoints, certificates, service etc for server service broker.

Should I have to login as sa to create those or I am fine with sbuser ?

Next step...in master database I create a user lets say proxysbuser which will be used to connect endpoints on both sides ie.initiator and target service brokers.

Then I i use proxysbuser to alter authorization of the peers certificate.

Am I in the right track ? Let me know.

Thanks,

Pramod

|||

Configuring dialog security (i.e. between services) is independent of configuring adjacent security (i.e. between instances) and should not be confused. For configuring adjacent security the steps are as follows:

1> Instance A: Create certificate owned by the dbo of master.
2> Instance A: Create SSB endpoint using the above certificate for authentication.
3> Instance A: Export certificate to \\shared\A.crt

4> Instance B: Create certificate owned by the dbo of master.
5> Instance B: Create SSB endpoint using the above certificate for authentication.
6> Instance B: Export certificate to \\shared\B.crt

7> Instance A: Create login for instance B, let's say InstanceB.
8> Instance A: Create user in master for login InstanceB.
9> Instance A: Import certificate \\shared\B.crt into master with owner InstanceB.
10> Instance A: Grant connect permission on SSB endpoint to login InstanceB.

11> Instance B: Create login for instance A, let's say InstanceA.
12> Instance B: Create user in master for login InstanceA.
13> Instance B: Import certificate \\shared\A.crt into master with owner InstanceA.
14> Instance B: Grant connect permission on SSB endpoint to login InstanceA.

The steps for securing dialogs are different from this. Refer to the docs for that.

If you find this tedious, you can use Remus' Service Listings Manager which automates this process for you.

Rushi

|||

Rushi:

I have been trying to use Remus Service Listing I have been refering to this link...https://blogs.msdn.com/remusrusanu/archive/2006/04/07/571066.aspx

In this step The administrator of the SQL Server instance hosting service ‘A’

In import mode the created script throws this error....

Msg 6522, Level 16, State 1, Procedure ssb_create_certificate_from_blob, Line 0 A .NET Framework error occurred during execution of user defined routine or aggregate 'ssb_create_certificate_from_blob': System.Data.SqlClient.SqlException: A certificate with name 'COSCOSB' already exists or this certificate already has been added to the database.
System.Data.SqlClient.SqlException:
at System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection)
at System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection)
at System.Data.SqlClient.SqlInternalConnectionSmi.EventSink.ProcessMessagesAndThrow(Boolean ignoreNonFatalMessages)
at Microsoft.SqlServer.Server.SmiEventSink_Default.ProcessMessagesAndThrow(Boolean ignoreNonFatalMessages)
at System.Data.SqlClient.SqlCommand.RunExecuteNonQuerySmi(Boolean sendToPipe)
at System.Data.SqlClient.SqlCommand.InternalExecuteNonQuery(DbAsyncResult result, String methodName, Boolean sendToPipe)
at System.Data.SqlClient.SqlCommand.ExecuteNonQuery()
at Microsoft.SqlServiceBroker.Samples.CertificatesBlob.CertificatesBlob.ssb_create_certificate_from_blob(SqlString databaseName, SqlString certificateName, SqlString authorizationUser, SqlBinary certificateBody)

The script which is throwing error is IF EXISTS(SELECT * FROM sys.certificates WHERE name = 'COSCOSB')
DROP CERTIFICATE [COSCOSB];
declare @.dbname sysname;
select @.dbname = DB_NAME();
print @.dbname -- this prints master
exec msdb.dbo.ssb_create_certificate_from_blob @.dbname, 'COSCOSB','COSCOSB',0x308201ED30820156A00302010202104B7566A1DEA72E844040F300FC947B6C300D06092A864886F70D010105050030353133303106035504031E2A0043004F00530043004F005F00430045005200540049004600490043004100540045005F005300550042301E170D3036303832373030303030305A170D3037303832383030303030305A30353133303106035504031E2A0043004F00530043004F005F00430045005200540049004600490043004100540045005F00530055004230819F300D06092A864886F70D010101050003818D0030818902818100D5DDA3F09C737A7F39E9E262C6B6C62524C3C8368750DC014AEE582FCDF97E29760C0452513414520FD8DB0A8CD3A389E15D0C5C5B006228145E405ADC2344ABF0DC08BF7647BEE413525C5E29B39107424479D70F25CD32F4FB95B43974E785C81410EF506EEC59E2C6CC6135F009300F5B496FF837E50AF8EB02F806CA99870203010001300D06092A864886F70D01010505000381810038C506E25FB74C59D08C58E56D9ED505A01AE0C33E5F28E5135D9E492F5E6B33703550E14042FF87EE83E8F8C43522EAEE9EDA417E7178BFB8BF7B5B27EA05926D4C52C9CAE9B7915A890422FCE67A4ED473E29154E1205A3CAF3245B0477A469192D409A0C5EB52BC307217CF7CA3C675F7305FC11503ECA17503EB1B493A4D;
GO

I dont have any certifcate in sys.certificates....why is it throwing error ? Could you pls tell me.

Thanks,
Pramod

.

|||

I think this is a known bug. I'm not sure if Remus has fixed it yet. You can try using the latest version and see if that works. Presently, Remus is on vacation, but I'll ask him to follow up on this bug when he gets back.

In the mean time, look at sys.certificates for any other certificate which may have been created (possibly with a different name).

Rushi

|||

Rushi:

Thanks for quick response...but I am sure i am using the latest version Service Lsiting Manager v1.1.3 which says that bug is fixed...sys.certifcates is empty. But will keep working on it.

Thanks,

Pramod

|||Are you in the right database?|||

Yup....I am in master....

|||

Rushi...my client db is standard sql2005 and server is developer sql2005 do u think that might be causing problem ?

|||No. The error is unrelated to licensing.|||On the correct instance? Service Listing Manager is simply running the SELECT * FROM sys.certificates query and finding a certificate but you are not.|||

Rushi:

Service Listing Manager is working fine in developer edition...I tried with 2 instances of standard edition on 2 different m/c it fails at this step exec msdb.dbo.ssb_create_certificate_from_blob @.dbname .......