(1) Move your message transformations to the ports: Thisminimizes the number of mes-sage copies created in your orchestration.
(2) Avoid using XmlDoc objects in your orchestration and use distinguished fields on amessage: XmlDoc objects load the full message into a DOM and consume a consider-able amount of memory resources. Each transformation from an XmlDoc to a messageobject and back results in copies of these objects being created in memory. Using distin-guished fields simply references the existing message and minimizes memory churn.
(3)Move data validation to the pipeline or schema: If you are performing any data valida-tion on your input messages, for example, validating that an order number is numericand within a prespecified range, you are better off specifying this form of validationwhen defining the data types in the schema. If you require other forms of contextualvalidation, you are better off doing that in a pipeline. It is better to do this before per-sisting the message to the Messagebox, running the routing logic to find the properschedule subscribed to the message instance, and then spawning an orchestrationinstance and allocating the required resources for it to run, only to realize that the datawas not good enough to start with and issues an exception or sends back an error. Youcan save a lot of system resources and processing time by handling this in the pipelineand generating an error message there that you can then route back to the sender usingcontent-based routing.
(4) Avoid using orchestrations for routing: If all your orchestration is doing is checkingmessage fields to route the message to the proper handler or another worker orches-tration to perform a particular task, strongly consider redesigning that piece of yourapplication as a set of port filters. Leverage receive ports with multiple receive loca-tions and send groups to route messages coming in from multiple sources and sendmessages to multiple destinations instead of relying on orchestrations to achieve that.•
(5) Avoid calls to external assemblies that perform extensive processing, especially if theycall web services or make calls to a database: Avoid calling slow external assembliesfrom within your orchestrations.5This holds the processing host resources and valuablehost threads from servicing other orchestration instances while waiting for that externallogic to terminate and return. If these calls stall or take a considerable amount of time,there is no way for the BizTalk engine to dehydrate that orchestration instance and usethe resources assigned to it to service another one, as the engine sees the instance’s stateas running while in fact the external code that it called is idle. Leverage the messaginginfrastructure to issue such calls that span multiple processes boundaries.
(6) Do not wrap calls to .NET objects in atomic transactions because they are nonserial-izable: Do not create transaction scopes around an expression to simply get around theshortcoming of an external object that you are using. If it makes sense, make this objectserializable, or if it is simply a utility, use static methods instead of instantiating anobject. Change the class’s implementation or implement a façade that provides youwith the required interface6if needed.
(7) Use Parallel shapes carefully: As illustrated in Figure 11-2, Parallel shapes should beused to parallelize receives if the order of incoming messages is unknown. The cost ofpersistence points associated with Parallel shapes is high.
(8) Differentiate between scopes and transactions: Transaction scopes affect persistencepoints. Atomic transactions batch state persistence points and write them to the data-base in a single call. Long-running transactions, on the other hand, persist state atdifferent points along the process. If you are not really running a transaction, do notassign a transaction type to your scope.•
Use pass-through pipelines where possible: The XMLSend or XMLReceive pipelines doa fair amount of work to validate and assemble the data going through them. If you aresure that outgoing and incoming messages are in a valid XML form, use a pass-throughpipeline to eliminate this unneeded overhead and make a some schedule work on C# or vb for Clean up suspended messages.