Custom Service and long running Workflow

I built a custom Service to listen to MessageQueue Messages:

using System.Workflow.Runtime.Messaging;
using System.Workflow.ComponentModel;
using System;
using System.Messaging;
using Microsoft.SharePoint;
using Microsoft.SharePoint.WebControls;
using Microsoft.SharePoint.WebPartPages;

namespace connvision.Sharepoint...

{

public class AskSharepointService : IAskSharepoint
{
string _SharepointSite;
System.Collections.Generic.Dictionary<string, Guid> KeyToProcess = new System.Collections.Generic.Dictionary<string, Guid>();

public string SharepointSite
{
get { return _SharepointSite; }
set { _SharepointSite = value; }
}
string _TaskList;

public string TaskList
{
get { return _TaskList; }
set { _TaskList = value; }
}

public void AskSharepointUser(Guid InstanceID, string ReferenceID)
{
MessageQueue usedQueue;
string QueuePath = ".\\PRIVATE$\\"+ ReferenceID;
if (!(MessageQueue.Exists(QueuePath)))
{
usedQueue = MessageQueue.Create(QueuePath);
usedQueue.Label = QueuePath;
}
else
{
usedQueue = new MessageQueue();
usedQueue.Path = QueuePath;

}
usedQueue.DenySharedReceive = true;
usedQueue.Formatter = new XmlMessageFormatter(new Type[] { typeof(String) });
usedQueue.ReceiveCompleted += new ReceiveCompletedEventHandler(usedQueue_ReceiveCompleted);
KeyToProcess.Add(ReferenceID, InstanceID);
usedQueue.BeginReceive(new TimeSpan(1, 0, 0, 0));
}


public void RaiseUserCanceld(Guid instanceId)
{
if (SharepointUserCanceled != null)
SharepointUserCanceled(null,
new WorkflowMessageEventArgs(instanceId));
}


// und ein Eventhandler wird definiert
// mit dem man ein Event des Workflows ausl?sen kann
public event EventHandler<WorkflowMessageEventArgs> SharepointUserCanceled;

void usedQueue_ReceiveCompleted(object sender, ReceiveCompletedEventArgs e)
{
MessageQueue actualQueue = (MessageQueue)sender;
System.Messaging.Message message = actualQueue.EndReceive(e.AsyncResult);
message.Formatter = new XmlMessageFormatter(new Type[] { typeof(String) });
string ActualRefferenceID = ((MessageQueue)sender).Label.Substring(11);
Guid ActualInstance = KeyToProcess[ActualRefferenceID];
//Guid ActualInstance = KeyToProcess[(string)message.Body];
KeyToProcess.Remove((string)message.Body);
RaiseUserCanceld(ActualInstance);
}
}
}

This works fine, but if I add the SqlServer Persistance Service, my service can't fire an event anymore. Do I have to load the Workflow again first? Would I have to do this with a delegate?

[2809 byte] By [Sha1-Hulud] at [2007-12-18]
# 1

Meanwhile I found the sample "RaiseEventToLoadWorkflow" from the SDK, but I don't see, where the workflow is loaded:

private void RaiseDocumentApprovalEvent(object stateInfo)
{
Console.WriteLine("\nHost: Loading workflow due to event firing...");

DocumentApprovalService da = stateInfo as DocumentApprovalService;
DocumentApproved(da.approver, new DocumentEventArgs(da.documentId));
}

?

Sha1-Hulud at 2007-9-8 > top of Msdn Tech,Software Development for Windows Vista,Windows Workflow Foundation...
# 2

If the Workflow is not in memory then the runtime will try to retrieve it from the persistence store and re-instantiate it.

edit: replaced store with service.

PjV at 2007-9-8 > top of Msdn Tech,Software Development for Windows Vista,Windows Workflow Foundation...
# 3

Does your workflow continue to properly execute with the exception of the missing events when you add the SqlPersistenceService? If there is any problem with the SQLPersistenceService, for example with SQL permissions, then it will abort your workflow, and if you do not have a WorkflowAborted handler to clear any waits then the workflow can appear to "hang" and could give the appearance of not responding to any events. A common cause for this is if the SQL server is on another machine than the machine that is executing the workflow. In this case System.Transaction will attempt to create a DTC transaction which requires network access to DTC. You can avoid this if all your database calls use the same connection string with a call like this:

// SQLPersistenceService
workflowRuntime.AddService(new SqlWorkflowPersistenceService(connectionString));
// Avoid the DTC transaction
workflowRuntime.AddService(new SharedConnectionWorkflowTransactionService(connectionString));

Thanks,
Steve Danielson, MCSD.NET
Microsoft Developer Support
This posting is provided "AS IS" with no warranties, and confers no rights.
For information and sample code for integrating Office with Visual Basic, Visual C++, Internet Scripts, and other programming languages, please see http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnoxpta/html/vsofficedev.asp. This site contains the most up-to-date information for using developer tools for Office integration and extensibility.
Are you secure? Please visit the Microsoft Security & Privacy Center (http://www.microsoft.com/security) for the latest news on security updates.

SteveDanielson at 2007-9-8 > top of Msdn Tech,Software Development for Windows Vista,Windows Workflow Foundation...
# 4

Hello Steve,

The SqlServer is on the same machine. The service was coded with beta 1.2 und now it comes to beta 2 i will rebuild it from scratch. I will tell how all works out with the new service.

Sha1-Hulud at 2007-9-8 > top of Msdn Tech,Software Development for Windows Vista,Windows Workflow Foundation...
# 5

Actually it's not about the machine where your SQL Server instance runs. If you use both the tracking service and the persistence service then the DTC will be required.

It seems most likely that you do not have the DTC installed. You should either do this, or add the lines of code that Steve recommended.

Regards,
Paul

PaulAndrew at 2007-9-8 > top of Msdn Tech,Software Development for Windows Vista,Windows Workflow Foundation...
# 6

I encountered the same problem, and I'm not very familiar with DTC.

Do I have to install DTC separately? Where do I get it from? Did anyone got the same problem, and got it fixed?

I have 2 different connection strings. one for the persistence service pointing to the WorkflowPersistence database, the other one points to the WorkflowTracking database. Which connectionString do I have to use for the SharedConnectionWorkflowTransactionService?

ConnectionString1 --> WorkflowPersistence

ConnectionString2 --> WorkflowTracking

After adding the services (I use following services):

SqlWorkflowPersistenceService persistenceService = new SqlWorkflowPersistenceService(connectionString1);

_workflowRuntime.AddService(persistenceService);

SharedConnectionWorkflowTransactionService sharedConnectionService = new SharedConnectionWorkflowTransactionService(connectionString2);

_workflowRuntime.AddService(sharedConnectionService);

SqlTrackingService trackingService = new SqlTrackingService(connectionString2);

_workflowRuntime.AddService(trackingService);

DefaultWorkflowSchedulerService schedulerService = new DefaultWorkflowSchedulerService();

_workflowRuntime.AddService(schedulerService);

ExternalDataExchangeService exchangeService = new ExternalDataExchangeService();

_workflowRuntime.AddService(exchangeService);

After adding these services I get an error when I call the Start method on the workflow runtime. Without the SharedConnectionWorkflowTransactionService it works fine. Well except that the Persistence and Tracking service wont work together.

Thanx for any replies

jamba8 at 2007-9-8 > top of Msdn Tech,Software Development for Windows Vista,Windows Workflow Foundation...
# 7

Thank you,Steve.

I have encountered the same problem as you mentioned before and solve it as your guid.

Actually the

SharedConnectionWorkflowTransactionService has been replaced by

SharedConnectionWorkflowCommitWorkBatchService in WWF 2.2.

Also the program can running, i still not understand why System.Transaction attempt to create a DTC transaction which requires network access to DTC if the SQL server is on another machine , and what DTC is.

so, can anybody tell me this?

thankyou,best regards!

Rodgers at 2007-9-8 > top of Msdn Tech,Software Development for Windows Vista,Windows Workflow Foundation...
# 8

Ok. I got my persistence and tracking service working, by putting everything into a single database.

Thanx

jamba8 at 2007-9-8 > top of Msdn Tech,Software Development for Windows Vista,Windows Workflow Foundation...
# 9

Hi Rodgers,

I can give you some information:

DTC is Distributed Transaction Coordinator.

I believe that my earlier post was incorrect. SharedConnectionWorkflowCommitWorkBatchService is not required when connecting to a remote SQL Server 2005, but I believe it may be required when connecting to SQL Server 2000, either remote or local due to differences in the way SQL 2000 and SQL 2005 are setup.

If you are using SqlWorkflowPersistenceService and SqlTrackingService together then DTC is required, but if you use SharedConnectionWorkflowCommitWorkBatchService then you will not need DTC.

Thanks

Steve Danielson [Microsoft]
This posting is provided "AS IS" with no warranties, and confers no rights.
Use of included script samples are subject to the terms specified at http://www.microsoft.com/info/cpyright.htm

SteveDanielson at 2007-9-8 > top of Msdn Tech,Software Development for Windows Vista,Windows Workflow Foundation...

Software Development for Windows Vista

Site Classified