SaveWorkflowAsyncResult.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / cdf / src / NetFx40 / System.Activities.DurableInstancing / System / Activities / DurableInstancing / SaveWorkflowAsyncResult.cs / 1305376 / SaveWorkflowAsyncResult.cs

                            //------------------------------------------------------------------------------ 
// Copyright (c) Microsoft Corporation.  All rights reserved.
//-----------------------------------------------------------------------------

namespace System.Activities.DurableInstancing 
{
    using System.Activities.Hosting; 
    using System.Collections; 
    using System.Collections.Generic;
    using System.Data; 
    using System.Data.SqlClient;
    using System.Globalization;
    using System.Linq;
    using System.Runtime; 
    using System.Runtime.DurableInstancing;
    using System.Text; 
    using System.Threading; 
    using System.Transactions;
    using System.Xml; 
    using System.Xml.Linq;

    sealed class SaveWorkflowAsyncResult : SqlWorkflowInstanceStoreAsyncResult
    { 
        const string createServiceDeploymentStoredProcedureParameters = @"@serviceDeploymentHash, @siteName, @relativeServicePath, @relativeApplicationPath,
                @serviceName, @serviceNamespace, @serviceDeploymentId output"; 
 
        const string storedProcedureParameters = @"@instanceId, @surrogateLockOwnerId, @handleInstanceVersion, @handleIsBoundToLock,
@primitiveDataProperties, @complexDataProperties, @writeOnlyPrimitiveDataProperties, @writeOnlyComplexDataProperties, @metadataProperties, 
@metadataIsConsistent, @encodingOption, @timerDurationMilliseconds, @suspensionStateChange, @suspensionReason, @suspensionExceptionName, @keysToAssociate,
@keysToComplete, @keysToFree, @concatenatedKeyProperties, @unlockInstance, @isReadyToRun, @isCompleted, @singleKeyId,
@lastMachineRunOn, @executionStatus, @blockingBookmarks, @workflowHostType, @serviceDeploymentId, @operationTimeout";
        static Dictionary serviceDeploymentIdsCache = new Dictionary(); 
        static ReaderWriterLockSlim serviceDeploymentIdsCacheLock = new ReaderWriterLockSlim();
        string commandText; 
 
        Guid serviceDeploymentHash;
        long serviceDeploymentId; 

        public SaveWorkflowAsyncResult
            (
            InstancePersistenceContext context, 
            InstancePersistenceCommand command,
            SqlWorkflowInstanceStore store, 
            SqlWorkflowInstanceStoreLock storeLock, 
            Transaction currentTransaction,
            TimeSpan timeout, 
            AsyncCallback callback,
            object state
            ) :
            base(context, command, store, storeLock, currentTransaction, timeout, callback, state) 
        {
            if (((SaveWorkflowCommand) command).InstanceKeyMetadataChanges.Count > 0) 
            { 
                throw FxTrace.Exception.AsError(new InstancePersistenceCommandException(SR.InstanceKeyMetadataChangesNotSupported));
            } 
        }

        protected override void GenerateSqlCommand(SqlCommand command)
        { 
            SaveWorkflowCommand saveWorkflowCommand = base.InstancePersistenceCommand as SaveWorkflowCommand;
            StringBuilder commandTextBuilder = new StringBuilder(SqlWorkflowInstanceStoreConstants.DefaultStringBuilderCapacity); 
            double operationTimeout = this.TimeoutHelper.RemainingTime().TotalMilliseconds; 
            SqlParameterCollection parameters = command.Parameters;
            string suspensionReason; 
            string suspensionExceptionName;

            parameters.Add(new SqlParameter { ParameterName = "@instanceId", SqlDbType = SqlDbType.UniqueIdentifier, Value = base.InstancePersistenceContext.InstanceView.InstanceId });
            parameters.Add(new SqlParameter { ParameterName = "@surrogateLockOwnerId", SqlDbType = SqlDbType.BigInt, Value = base.StoreLock.SurrogateLockOwnerId }); 
            parameters.Add(new SqlParameter { ParameterName = "@handleInstanceVersion", SqlDbType = SqlDbType.BigInt, Value = base.InstancePersistenceContext.InstanceVersion});
            parameters.Add(new SqlParameter { ParameterName = "@handleIsBoundToLock", SqlDbType = SqlDbType.Bit, Value = base.InstancePersistenceContext.InstanceView.IsBoundToLock }); 
            parameters.Add(new SqlParameter { ParameterName = "@timerDurationMilliseconds", SqlDbType = SqlDbType.BigInt, Value = (object) GetPendingTimerExpiration(saveWorkflowCommand) ?? DBNull.Value }); 
            parameters.Add(new SqlParameter { ParameterName = "@unlockInstance", SqlDbType = SqlDbType.Bit, Value = saveWorkflowCommand.UnlockInstance });
            parameters.Add(new SqlParameter { ParameterName = "@suspensionStateChange", SqlDbType = SqlDbType.TinyInt, Value = GetSuspensionReason(saveWorkflowCommand, out suspensionReason, out suspensionExceptionName) }); 
            parameters.Add(new SqlParameter { ParameterName = "@suspensionReason", SqlDbType = SqlDbType.NVarChar, Value = (object) suspensionReason ?? DBNull.Value });
            parameters.Add(new SqlParameter { ParameterName = "@suspensionExceptionName", SqlDbType = SqlDbType.NVarChar, Size = 450, Value = (object) suspensionExceptionName ?? DBNull.Value });
            parameters.Add(new SqlParameter { ParameterName = "@isCompleted", SqlDbType = SqlDbType.Bit, Value = saveWorkflowCommand.CompleteInstance });
            parameters.Add(new SqlParameter { ParameterName = "@isReadyToRun", SqlDbType = SqlDbType.Bit, Value = IsReadyToRun(saveWorkflowCommand) }); 
            parameters.Add(new SqlParameter { ParameterName = "@workflowHostType", SqlDbType = SqlDbType.UniqueIdentifier, Value = (object) GetWorkflowHostType(saveWorkflowCommand) ?? DBNull.Value});
            parameters.Add(new SqlParameter { ParameterName = "@operationTimeout", SqlDbType = SqlDbType.Int, Value = (operationTimeout < Int32.MaxValue) ? Convert.ToInt32(operationTimeout) : Int32.MaxValue }); 
 
            commandTextBuilder.AppendLine(@"set nocount on
 	                                        set transaction isolation level read committed		 
	                                        set xact_abort on
                                            begin transaction");

            ExtractServiceDeploymentInformation(saveWorkflowCommand, commandTextBuilder, parameters); 

            commandTextBuilder.AppendLine("declare @result int"); 
            commandTextBuilder.AppendLine(string.Format(CultureInfo.InvariantCulture, "exec @result = {0}.[SaveInstance] {1} ;", 
                SqlWorkflowInstanceStoreConstants.DefaultSchema, SaveWorkflowAsyncResult.storedProcedureParameters));
            commandTextBuilder.AppendLine("if (@result = 0)"); 
            commandTextBuilder.AppendLine("begin");

            SerializeAssociatedData(parameters, saveWorkflowCommand, commandTextBuilder);
 
            commandTextBuilder.AppendLine("commit transaction");
            commandTextBuilder.AppendLine("end"); 
            commandTextBuilder.AppendLine("else"); 
            commandTextBuilder.AppendLine("rollback transaction");
 
            this.commandText = commandTextBuilder.ToString();
        }

        protected override string GetSqlCommandText() 
        {
            return this.commandText; 
        } 

        protected override CommandType GetSqlCommandType() 
        {
            return CommandType.Text;
        }
 
        protected override Exception ProcessSqlResult(SqlDataReader reader)
        { 
            Exception exception = StoreUtilities.GetNextResultSet(base.InstancePersistenceCommand.Name, reader); 

            if (exception == null) 
            {
                SaveWorkflowCommand saveWorkflowCommand = base.InstancePersistenceCommand as SaveWorkflowCommand;
                InstanceLockTracking instanceLockTracking = (InstanceLockTracking)(base.InstancePersistenceContext.UserContext);
                if ((this.serviceDeploymentHash != Guid.Empty) && (this.serviceDeploymentId == 0)) 
                {
                    this.serviceDeploymentId = reader.GetInt64(1); 
                    PutServiceDeploymentId(); 
                    exception = StoreUtilities.GetNextResultSet(base.InstancePersistenceCommand.Name, reader);
                } 

                if (exception == null)
                {
                    if (!base.InstancePersistenceContext.InstanceView.IsBoundToLock) 
                    {
                        long instanceVersion = reader.GetInt64(1); 
                        instanceLockTracking.TrackStoreLock(base.InstancePersistenceContext.InstanceView.InstanceId, instanceVersion, this.DependentTransaction); 
                        base.InstancePersistenceContext.BindAcquiredLock(instanceVersion);
                    } 

                    if (saveWorkflowCommand.InstanceData.Count > 0)
                    {
                        base.InstancePersistenceContext.PersistedInstance(saveWorkflowCommand.InstanceData); 
                    }
 
                    SaveWorkflowAsyncResult.UpdateKeyData(base.InstancePersistenceContext, saveWorkflowCommand); 

                    foreach (KeyValuePair property in saveWorkflowCommand.InstanceMetadataChanges) 
                    {
                        base.InstancePersistenceContext.WroteInstanceMetadataValue(property.Key, property.Value);
                    }
 
                    if (saveWorkflowCommand.CompleteInstance)
                    { 
                        base.InstancePersistenceContext.CompletedInstance(); 
                    }
 
                    if (saveWorkflowCommand.UnlockInstance || saveWorkflowCommand.CompleteInstance)
                    {
                        instanceLockTracking.TrackStoreUnlock(this.DependentTransaction);
                        base.InstancePersistenceContext.InstanceHandle.Free(); 
                    }
                } 
                else if (exception is InstanceLockLostException) 
                {
                    base.InstancePersistenceContext.InstanceHandle.Free(); 
                }
            }

            return exception; 
        }
 
        static void AddSerializedProperty(ArraySegment source, SqlParameterCollection parameters, string parameterName) 
        {
            int parameterSize = source.Count > 8000 ? source.Count : -1; 
            object parameterValue = (parameterSize == -1 ? SaveWorkflowAsyncResult.GenerateByteArray(source) : source.Array) ?? (object) DBNull.Value;
            parameters.Add(new SqlParameter { ParameterName = parameterName, SqlDbType = SqlDbType.VarBinary, Size = parameterSize, Value = parameterValue });
        }
 
        static byte[] GenerateByteArray(ArraySegment source)
        { 
            if (source.Array != null) 
            {
                byte[] destination = new byte[source.Count]; 
                Buffer.BlockCopy(source.Array, 0, destination, 0, source.Count);
                return destination;
            }
 
            return null;
        } 
 
        static string GetBlockingBookmarks(SaveWorkflowCommand saveWorkflowCommand)
        { 
            string blockingBookmarks = null;
            InstanceValue binaryBlockingBookmarks;

            if (saveWorkflowCommand.InstanceData.TryGetValue(SqlWorkflowInstanceStoreConstants.BinaryBlockingBookmarksPropertyName, out binaryBlockingBookmarks)) 
            {
                StringBuilder bookmarkListBuilder = new StringBuilder(SqlWorkflowInstanceStoreConstants.DefaultStringBuilderCapacity); 
                IEnumerable activeBookmarks = binaryBlockingBookmarks.Value as IEnumerable; 

                foreach (BookmarkInfo bookmarkInfo in activeBookmarks) 
                {
                    bookmarkListBuilder.AppendFormat(CultureInfo.InvariantCulture, "[{0}: {1}]{2}", bookmarkInfo.BookmarkName, bookmarkInfo.OwnerDisplayName, Environment.NewLine);
                }
 
                blockingBookmarks = bookmarkListBuilder.ToString();
            } 
 
            return blockingBookmarks;
        } 

        static string GetExecutionStatus(SaveWorkflowCommand saveWorkflowCommand)
        {
            string executionStatus = null; 
            InstanceValue executionStatusProperty;
 
            if (saveWorkflowCommand.InstanceData.TryGetValue(SqlWorkflowInstanceStoreConstants.StatusPropertyName, out executionStatusProperty)) 
            {
                executionStatus = (string) executionStatusProperty.Value; 
            }

            return executionStatus;
        } 

        static Int64? GetPendingTimerExpiration(SaveWorkflowCommand saveWorkflowCommand) 
        { 
            InstanceValue pendingTimerExpirationPropertyValue;
 
            if (saveWorkflowCommand.InstanceData.TryGetValue(SqlWorkflowInstanceStoreConstants.PendingTimerExpirationPropertyName, out pendingTimerExpirationPropertyValue))
            {
                DateTime pendingTimerExpiration = ((DateTime) pendingTimerExpirationPropertyValue.Value).ToUniversalTime();
                TimeSpan datetimeOffset = pendingTimerExpiration - DateTime.UtcNow; 

                return (Int64) datetimeOffset.TotalMilliseconds; 
            } 

            return null; 
        }

        static SuspensionStateChange GetSuspensionReason(SaveWorkflowCommand saveWorkflowCommand, out string suspensionReason, out string suspensionExceptionName)
        { 
            IDictionary instanceMetadataChanges = saveWorkflowCommand.InstanceMetadataChanges;
            SuspensionStateChange suspensionStateChange = SuspensionStateChange.NoChange; 
            InstanceValue propertyValue; 
            suspensionReason = null;
            suspensionExceptionName = null; 

            if (instanceMetadataChanges.TryGetValue(WorkflowServiceNamespace.SuspendReason, out propertyValue))
            {
                if (!propertyValue.IsDeletedValue) 
                {
                    suspensionStateChange = SuspensionStateChange.SuspendInstance; 
                    suspensionReason = (string) propertyValue.Value; 

                    if (instanceMetadataChanges.TryGetValue(WorkflowServiceNamespace.SuspendException, out propertyValue) && !propertyValue.IsDeletedValue) 
                    {
                        suspensionExceptionName = ((Exception) propertyValue.Value).GetType().ToString();
                    }
                } 
                else
                { 
                    suspensionStateChange = SuspensionStateChange.UnsuspendInstance; 
                }
            } 

            return suspensionStateChange;
        }
 
        static Guid? GetWorkflowHostType(SaveWorkflowCommand saveWorkflowCommand)
        { 
            InstanceValue instanceValue; 
            if (saveWorkflowCommand.InstanceMetadataChanges.TryGetValue(WorkflowNamespace.WorkflowHostType, out instanceValue))
            { 
                XName workflowHostType = instanceValue.Value as XName;

                if (workflowHostType == null)
                { 
                    throw FxTrace.Exception.AsError(new InstancePersistenceCommandException(SR.InvalidWorkflowHostTypeValue(WorkflowNamespace.WorkflowHostType)));
                } 
                byte[] workflowHostTypeBuffer = Encoding.Unicode.GetBytes(((XName) instanceValue.Value).ToString()); 
                return new Guid(HashHelper.ComputeHash(workflowHostTypeBuffer));
            } 
            return null;
        }

        static bool IsReadyToRun(SaveWorkflowCommand saveWorkflowCommand) 
        {
            InstanceValue statusPropertyValue; 
 
            if (saveWorkflowCommand.InstanceData.TryGetValue(SqlWorkflowInstanceStoreConstants.StatusPropertyName, out statusPropertyValue) &&
                ((string) statusPropertyValue.Value) == SqlWorkflowInstanceStoreConstants.ExecutingStatusPropertyValue) 
            {
                return true;
            }
 
            return false;
        } 
 
        static void UpdateKeyData(InstancePersistenceContext context, SaveWorkflowCommand saveWorkflowCommand)
        { 
            InstanceView instanceView = context.InstanceView;

            foreach (KeyValuePair> keyEntry in saveWorkflowCommand.InstanceKeysToAssociate)
            { 
                if (!instanceView.InstanceKeys.ContainsKey(keyEntry.Key))
                { 
                    context.AssociatedInstanceKey(keyEntry.Key); 

                    if (keyEntry.Value != null) 
                    {
                        foreach (KeyValuePair property in keyEntry.Value)
                        {
                            context.WroteInstanceKeyMetadataValue(keyEntry.Key, property.Key, property.Value); 
                        }
                    } 
                } 
            }
 
            foreach (Guid key in saveWorkflowCommand.InstanceKeysToComplete)
            {
                InstanceKeyView existingKeyView;
                if (instanceView.InstanceKeys.TryGetValue(key, out existingKeyView)) 
                {
                    if (existingKeyView.InstanceKeyState != InstanceKeyState.Completed) 
                    { 
                        context.CompletedInstanceKey(key);
                    } 
                }
            }

            foreach (Guid key in saveWorkflowCommand.InstanceKeysToFree) 
            {
                InstanceKeyView existingKeyView; 
                if (instanceView.InstanceKeys.TryGetValue(key, out existingKeyView)) 
                {
                    context.UnassociatedInstanceKey(key); 
                }
            }

            foreach (KeyValuePair> keyEntry in saveWorkflowCommand.InstanceKeyMetadataChanges) 
            {
                if (keyEntry.Value != null) 
                { 
                    foreach (KeyValuePair property in keyEntry.Value)
                    { 
                        context.WroteInstanceKeyMetadataValue(keyEntry.Key, property.Key, property.Value);
                    }
                }
            } 

            if (saveWorkflowCommand.CompleteInstance) 
            { 
                foreach (KeyValuePair instanceKeys in instanceView.InstanceKeys)
                { 
                    if (instanceKeys.Value != null)
                    {
                        if (instanceKeys.Value.InstanceKeyState == InstanceKeyState.Associated)
                        { 
                            context.CompletedInstanceKey(instanceKeys.Key);
                        } 
                    } 
                }
            } 
        }

        void ExtractServiceDeploymentInformation(SaveWorkflowCommand saveWorkflowCommand, StringBuilder commandTextBuilder, SqlParameterCollection parameters)
        { 
            InstanceValue instanceValue;
            //Extract the activation parameters 
            string serviceName = null; 
            string serviceNamespace = null;
            string site = null; 
            string relativeApplicationPath = null;
            string relativeServicePath = null;

            if (saveWorkflowCommand.InstanceMetadataChanges.TryGetValue(PersistenceMetadataNamespace.ActivationType, out instanceValue)) 
            {
                if (PersistenceMetadataNamespace.ActivationTypes.WAS.Equals(instanceValue.Value)) 
                { 
                    if (saveWorkflowCommand.InstanceMetadataChanges.TryGetValue(WorkflowServiceNamespace.Service, out instanceValue))
                    { 
                        serviceName = ((XName) instanceValue.Value).LocalName;
                        serviceNamespace = ((XName) instanceValue.Value).Namespace.NamespaceName;
                    }
                    if (saveWorkflowCommand.InstanceMetadataChanges.TryGetValue(WorkflowServiceNamespace.SiteName, out instanceValue)) 
                    {
                        site = (string) instanceValue.Value; 
                    } 
                    if (saveWorkflowCommand.InstanceMetadataChanges.TryGetValue(WorkflowServiceNamespace.RelativeApplicationPath, out instanceValue))
                    { 
                        relativeApplicationPath = (string) instanceValue.Value;
                    }
                    if (saveWorkflowCommand.InstanceMetadataChanges.TryGetValue(WorkflowServiceNamespace.RelativeServicePath, out instanceValue))
                    { 
                        relativeServicePath = (string) instanceValue.Value;
                    } 
 
                    byte[] serviceDeploymentHashBuffer = Encoding.Unicode.GetBytes(string.Format(CultureInfo.InvariantCulture, "{0}#{1}#{2}#{3}#{4}",
                        serviceName ?? string.Empty, serviceNamespace ?? string.Empty, site ?? string.Empty, relativeApplicationPath ?? string.Empty, relativeServicePath ?? string.Empty)); 
                    this.serviceDeploymentHash = new Guid(HashHelper.ComputeHash(serviceDeploymentHashBuffer));

                    //Get the service id has been seen before, get it from the cache
                    GetServiceDeploymentId(); 
                }
                else 
                { 
                    throw FxTrace.Exception.AsError(new InstancePersistenceCommandException(SR.NonWASActivationNotSupported));
                } 
            }

            if ((this.serviceDeploymentHash != Guid.Empty) && (this.serviceDeploymentId == 0))
            { 
                //This is the first time we see this service deployment so we need to create a new entry for it before creating the instance
                commandTextBuilder.AppendLine("declare @serviceDeploymentId bigint"); 
                commandTextBuilder.AppendLine(string.Format(CultureInfo.InvariantCulture, "exec {0}.[CreateServiceDeployment] {1} ;", 
                    SqlWorkflowInstanceStoreConstants.DefaultSchema, SaveWorkflowAsyncResult.createServiceDeploymentStoredProcedureParameters));
 
                parameters.Add(new SqlParameter { ParameterName = "@serviceDeploymentHash", SqlDbType = SqlDbType.UniqueIdentifier, Value = this.serviceDeploymentHash });
                parameters.Add(new SqlParameter { ParameterName = "@serviceName", Size = -1, SqlDbType = SqlDbType.NVarChar, Value = serviceName ?? (object) DBNull.Value });
                parameters.Add(new SqlParameter { ParameterName = "@serviceNamespace", Size = -1, SqlDbType = SqlDbType.NVarChar, Value = serviceNamespace ?? (object) DBNull.Value });
                parameters.Add(new SqlParameter { ParameterName = "@siteName", Size = -1, SqlDbType = SqlDbType.NVarChar, Value = site ?? (object) DBNull.Value }); 
                parameters.Add(new SqlParameter { ParameterName = "@relativeServicePath", Size = -1, SqlDbType = SqlDbType.NVarChar, Value = relativeServicePath ?? (object) DBNull.Value });
                parameters.Add(new SqlParameter { ParameterName = "@relativeApplicationPath", Size = -1, SqlDbType = SqlDbType.NVarChar, Value = relativeApplicationPath ?? (object) DBNull.Value }); 
            } 
            else
            { 
                parameters.Add(new SqlParameter { ParameterName = "@serviceDeploymentId", SqlDbType = SqlDbType.BigInt, Value = (this.serviceDeploymentId != 0) ? (object) this.serviceDeploymentId : (object) DBNull.Value});
            }
        }
 
        void GetServiceDeploymentId()
        { 
            try 
            {
                SaveWorkflowAsyncResult.serviceDeploymentIdsCacheLock.EnterReadLock(); 
                SaveWorkflowAsyncResult.serviceDeploymentIdsCache.TryGetValue(this.serviceDeploymentHash, out this.serviceDeploymentId);
            }
            finally
            { 
                SaveWorkflowAsyncResult.serviceDeploymentIdsCacheLock.ExitReadLock();
            } 
        } 

        void PutServiceDeploymentId() 
        {
            try
            {
                serviceDeploymentIdsCacheLock.EnterWriteLock(); 
                serviceDeploymentIdsCache[this.serviceDeploymentHash] = this.serviceDeploymentId;
            } 
            finally 
            {
                serviceDeploymentIdsCacheLock.ExitWriteLock(); 
            }
        }

        void SerializeAssociatedData(SqlParameterCollection parameters, SaveWorkflowCommand saveWorkflowCommand, StringBuilder commandTextBuilder) 
        {
            if (saveWorkflowCommand.CompleteInstance && base.Store.InstanceCompletionAction == InstanceCompletionAction.DeleteAll) 
            { 
                parameters.Add(new SqlParameter { ParameterName = "@keysToAssociate", SqlDbType = SqlDbType.Xml, Value = DBNull.Value });
                parameters.Add(new SqlParameter { ParameterName = "@singleKeyId", SqlDbType = SqlDbType.UniqueIdentifier, Value = DBNull.Value }); 
                parameters.Add(new SqlParameter { ParameterName = "@keysToComplete", SqlDbType = SqlDbType.Xml, Value = DBNull.Value });
                parameters.Add(new SqlParameter { ParameterName = "@keysToFree", SqlDbType = SqlDbType.Xml, Value = DBNull.Value });
                parameters.Add(new SqlParameter { ParameterName = "@concatenatedKeyProperties", SqlDbType = SqlDbType.VarBinary, Value = DBNull.Value });
                parameters.Add(new SqlParameter { ParameterName = "@primitiveDataProperties", SqlDbType = SqlDbType.VarBinary, Value = DBNull.Value }); 
                parameters.Add(new SqlParameter { ParameterName = "@complexDataProperties", SqlDbType = SqlDbType.VarBinary, Value = DBNull.Value });
                parameters.Add(new SqlParameter { ParameterName = "@writeOnlyPrimitiveDataProperties", SqlDbType = SqlDbType.VarBinary, Value = DBNull.Value }); 
                parameters.Add(new SqlParameter { ParameterName = "@writeOnlyComplexDataProperties", SqlDbType = SqlDbType.VarBinary, Value = DBNull.Value }); 
                parameters.Add(new SqlParameter { ParameterName = "@metadataProperties", SqlDbType = SqlDbType.VarBinary, Value = DBNull.Value });
                parameters.Add(new SqlParameter { ParameterName = "@metadataIsConsistent", SqlDbType = SqlDbType.Bit, Value = DBNull.Value }); 
                parameters.Add(new SqlParameter { ParameterName = "@encodingOption", SqlDbType = SqlDbType.TinyInt, Value = DBNull.Value });
                parameters.Add(new SqlParameter { ParameterName = "@lastMachineRunOn", SqlDbType = SqlDbType.NVarChar, Value = DBNull.Value });
                parameters.Add(new SqlParameter { ParameterName = "@executionStatus", SqlDbType = SqlDbType.NVarChar, Value = DBNull.Value });
                parameters.Add(new SqlParameter { ParameterName = "@blockingBookmarks", SqlDbType = SqlDbType.NVarChar, Value = DBNull.Value }); 

                return; 
            } 

            List keysToAssociate = CorrelationKey.BuildKeyList(saveWorkflowCommand.InstanceKeysToAssociate, base.Store.InstanceEncodingOption); 
            List keysToComplete = CorrelationKey.BuildKeyList(saveWorkflowCommand.InstanceKeysToComplete);
            List keysToFree = CorrelationKey.BuildKeyList(saveWorkflowCommand.InstanceKeysToFree);
            ArraySegment[] dataProperties = SerializationUtilities.SerializePropertyBag(saveWorkflowCommand.InstanceData, base.Store.InstanceEncodingOption);
            ArraySegment metadataProperties = SerializationUtilities.SerializeMetadataPropertyBag(saveWorkflowCommand, base.InstancePersistenceContext, base.Store.InstanceEncodingOption); 
            byte[] concatenatedKeyProperties = SerializationUtilities.CreateKeyBinaryBlob(keysToAssociate);
            bool metadataConsistency = (base.InstancePersistenceContext.InstanceView.InstanceMetadataConsistency == InstanceValueConsistency.None); 
            bool singleKeyToAssociate = (keysToAssociate != null && keysToAssociate.Count == 1); 

            parameters.Add(new SqlParameter { ParameterName = "@keysToAssociate", SqlDbType = SqlDbType.Xml, Value = singleKeyToAssociate ? DBNull.Value : SerializationUtilities.CreateCorrelationKeyXmlBlob(keysToAssociate) }); 
            parameters.Add(new SqlParameter { ParameterName = "@singleKeyId", SqlDbType = SqlDbType.UniqueIdentifier, Value = singleKeyToAssociate ? keysToAssociate[0].KeyId : (object) DBNull.Value });
            parameters.Add(new SqlParameter { ParameterName = "@keysToComplete", SqlDbType = SqlDbType.Xml, Value = SerializationUtilities.CreateCorrelationKeyXmlBlob(keysToComplete) });
            parameters.Add(new SqlParameter { ParameterName = "@keysToFree", SqlDbType = SqlDbType.Xml, Value = SerializationUtilities.CreateCorrelationKeyXmlBlob(keysToFree) });
            parameters.Add(new SqlParameter { ParameterName = "@concatenatedKeyProperties", SqlDbType = SqlDbType.VarBinary, Size = -1, Value = (object) concatenatedKeyProperties ?? DBNull.Value }); 
            parameters.Add(new SqlParameter { ParameterName = "@metadataIsConsistent", SqlDbType = SqlDbType.Bit, Value = metadataConsistency });
            parameters.Add(new SqlParameter { ParameterName = "@encodingOption", SqlDbType = SqlDbType.TinyInt, Value = base.Store.InstanceEncodingOption }); 
            parameters.Add(new SqlParameter { ParameterName = "@lastMachineRunOn", SqlDbType = SqlDbType.NVarChar, Size = 450, Value = SqlWorkflowInstanceStoreConstants.MachineName }); 
            parameters.Add(new SqlParameter { ParameterName = "@executionStatus", SqlDbType = SqlDbType.NVarChar, Size = 450, Value = GetExecutionStatus(saveWorkflowCommand) ?? (object) DBNull.Value });
            parameters.Add(new SqlParameter { ParameterName = "@blockingBookmarks", SqlDbType = SqlDbType.NVarChar, Size = -1, Value = GetBlockingBookmarks(saveWorkflowCommand) ?? (object) DBNull.Value }); 

            ArraySegment[] properties = { dataProperties[0], dataProperties[1], dataProperties[2], dataProperties[3], metadataProperties };
            string[] dataPropertyParameters = { "@primitiveDataProperties", "@complexDataProperties", "@writeOnlyPrimitiveDataProperties", @"writeOnlyComplexDataProperties", "@metadataProperties" };
 
            for (int i = 0; i < 5; i++)
            { 
                SaveWorkflowAsyncResult.AddSerializedProperty(properties[i], parameters, dataPropertyParameters[i]); 
            }
 
            this.SerializePromotedProperties(parameters, commandTextBuilder, saveWorkflowCommand);
        }

        void SerializePromotedProperties(SqlParameterCollection parameters, StringBuilder commandTextBuilder, SaveWorkflowCommand saveWorkflowCommand) 
        {
            const int SqlVariantStartColumn = 1; 
            const string promotionNameParameter = "@promotionName="; 
            const string instanceIdParameter = "@instanceId=";
            int promotionNumber = 0; 

            foreach (KeyValuePair, List>> promotion in base.Store.Promotions)
            {
                StringBuilder storedProcInvocationBuilder = new StringBuilder(SqlWorkflowInstanceStoreConstants.DefaultStringBuilderCapacity); 
                int column = SqlVariantStartColumn;
                bool addPromotion = false; 
                string promotionNameArgument = string.Format(CultureInfo.InvariantCulture, "@promotionName{0}", promotionNumber); 
                string instanceIdArgument = string.Format(CultureInfo.InvariantCulture, "@instanceId{0}", promotionNumber);
 
                storedProcInvocationBuilder.Append(string.Format(CultureInfo.InvariantCulture, "exec {0}.[InsertPromotedProperties] ", SqlWorkflowInstanceStoreConstants.DefaultSchema));
                storedProcInvocationBuilder.Append(promotionNameParameter);
                storedProcInvocationBuilder.Append(promotionNameArgument);
                storedProcInvocationBuilder.Append(","); 
                storedProcInvocationBuilder.Append(instanceIdParameter);
                storedProcInvocationBuilder.Append(instanceIdArgument); 
 
                foreach (XName name in promotion.Value.Item1)
                { 
                    InstanceValue propertyValue;

                    if (saveWorkflowCommand.InstanceData.TryGetValue(name, out propertyValue))
                    { 
                        if (!SerializationUtilities.IsPropertyTypeSqlVariantCompatible(propertyValue))
                        { 
                            throw FxTrace.Exception.AsError(new InstancePersistenceException(SR.CannotPromoteAsSqlVariant(propertyValue.Value.GetType().ToString(), name.ToString()))); 
                        }
 
                        string parameterName = string.Format(CultureInfo.InvariantCulture, "@value{0}=", column);
                        string argumentName = string.Format(CultureInfo.InvariantCulture, "@value{0}_promotion{1}", column, promotionNumber);
                        parameters.Add(new SqlParameter() { SqlDbType = SqlDbType.Variant, ParameterName = argumentName, Value = propertyValue.Value ?? DBNull.Value});
 
                        storedProcInvocationBuilder.Append(", ");
                        storedProcInvocationBuilder.Append(parameterName); 
                        storedProcInvocationBuilder.Append(argumentName); 
                        addPromotion = true;
                    } 
                    column++;
                }

                column = SqlVariantStartColumn + SqlWorkflowInstanceStoreConstants.MaximumPropertiesPerPromotion; 

                foreach (XName name in promotion.Value.Item2) 
                { 
                    InstanceValue propertyValue;
                    IObjectSerializer serializer = ObjectSerializerFactory.GetObjectSerializer(base.Store.InstanceEncodingOption); 

                    if (saveWorkflowCommand.InstanceData.TryGetValue(name, out propertyValue))
                    {
                        string parameterName = string.Format(CultureInfo.InvariantCulture, "@value{0}=", column); 
                        string argumentName = string.Format(CultureInfo.InvariantCulture, "@value{0}_promotion{1}", column, promotionNumber);
 
                        SaveWorkflowAsyncResult.AddSerializedProperty(serializer.SerializeValue(propertyValue.Value), parameters, argumentName); 
                        storedProcInvocationBuilder.Append(", ");
                        storedProcInvocationBuilder.Append(parameterName); 
                        storedProcInvocationBuilder.Append(argumentName);
                        addPromotion = true;
                    }
                    column++; 
                }
 
                if (addPromotion) 
                {
                    parameters.Add(new SqlParameter() { SqlDbType = SqlDbType.NVarChar, Size = 400, ParameterName = promotionNameArgument, Value = promotion.Key }); 
                    parameters.Add(new SqlParameter() { SqlDbType = SqlDbType.UniqueIdentifier, ParameterName = instanceIdArgument, Value = base.InstancePersistenceContext.InstanceView.InstanceId });
                    storedProcInvocationBuilder.Append(";");
                    commandTextBuilder.AppendLine(storedProcInvocationBuilder.ToString());
                    promotionNumber++; 
                }
            } 
        } 
    }
} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.


                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK