Hello,
Sometimes we have contention problems in database because of the transaction isolation level when we execute a lot of inserts in parallel. To avoid this, if the business allows it, it is useful to “downgrade” the isolation level of .NET transactions. By default, in the .NET framework, it is set to Serializable, but usually we want to use ReadCommited or anything lower instead.
In WCF is easy to change , and in the WF’s TransactionScopes you have a beautiful combo to do it.
But what can we do with the TransactedReceiveScope activity? It doesn’t have any combo to modify the isolation level. It imitates the WCF’s TransactionScopeRequired but we can not set the isolation level of the Workflow easily in the ServiceBehaviour of the header.
At this point we only have one way, create and assign the behaviour by a BehaviourExtensionElement and assign it by configuration. The behaviour:
/// <summary> /// Service behaviour that changes the default WCF/WF transaction isolation to ReadCommitted. /// http://social.msdn.microsoft.com/Forums/en/wfprerelease/thread/5c4f1c0f-9183-46ae-8c6e-08bdfaa93fd8 /// </summary> public class ReadCommittedServiceBehaviour : BehaviorExtensionElement ,IServiceBehavior { public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, Collection endpoints, BindingParameterCollection bindingParameters) { } public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase) { //this looks for the ServiceBehaviour. var serviceBehaviour = serviceDescription.Behaviors.FirstOrDefault(b => b.GetType() == typeof(ServiceBehaviorAttribute)) as ServiceBehaviorAttribute; //if it doesn't exist... WF XAMLX case add a ServiceBehaviourAttribute, if exists(WCF case) modify it. if (serviceBehaviour == null) { serviceDescription.Behaviors.Add(new ServiceBehaviorAttribute() { TransactionIsolationLevel = IsolationLevel.ReadCommitted }); } else { //remove it and add it again, this way it gets the isolation level serviceDescription.Behaviors.Remove(typeof(ServiceBehaviorAttribute)); serviceDescription.Behaviors.Add(serviceBehaviour); serviceBehaviour.TransactionIsolationLevel = IsolationLevel.ReadCommitted; } } public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase) { } public override Type BehaviorType { get { return typeof(ReadCommittedServiceBehaviour); } } protected override object CreateBehavior() { return new ReadCommittedServiceBehaviour(); } }
And we tell the IIS app to use it, notice the <ReadCommittedBehaviour /> at the end of the behaviour section.
<system.serviceModel> <extensions> <behaviorExtensions> <add name="ReadCommittedBehaviour" type="TransactionsAndExceptions.ReadCommittedServiceBehaviour, TransactionsAndExceptions" /> </behaviorExtensions> </extensions> <behaviors> <serviceBehaviors> <behavior> <!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment --> <serviceMetadata httpGetEnabled="true" /> <!-- To receive exception details in faults for debugging purposes, set the value below to true. Set to false before deployment to avoid disclosing exception information --> <serviceDebug includeExceptionDetailInFaults="false" /> <sqlWorkflowInstanceStore instanceCompletionAction="DeleteAll" instanceEncodingOption="None" instanceLockedExceptionAction="NoRetry" connectionStringName="ApplicationServerWorkflowInstanceStoreConnectionString" hostLockRenewalPeriod="00:00:30" runnableInstancesDetectionPeriod="00:00:05" /> <workflowInstanceManagement authorizedWindowsGroup="AS_Administrators" /> <workflowUnhandledException action="Abandon" /> <workflowIdle timeToPersist="00:00:00" timeToUnload="00:01:00" /> <dataContractSerializer maxItemsInObjectGraph="2147483647" /> <ReadCommittedBehaviour /> </behavior> </serviceBehaviors> </behaviors> <serviceHostingEnvironment multipleSiteBindingsEnabled="true" /> </system.serviceModel>
Hope this helps
[…] Well, as I have explained before, the TransactedReceiveScope activity creates a serializable transaction that causes blocks. I have used a tag to modify this behaviour and create a ReadCommitted transaction, but it doesn̵… […]