Today, I will bring back to life an old BizTalk Server blog post by an old friend of mine, Thomas Canter, with his permission, that I find pretty interesting and useful: The maligned Distinguished Field or why Distinguished Fields are cool.
The Distinguished Field is often seen as the weaker of the two types of Fields when handling Fields in BizTalk.
After all, the Distinguished Field can’t be used as a filter on a message, and it’s slower than its big brother the Promoted Field.
Well, today I’m here to dispel the myth of the wimpy Distinguished Field and place in the pantheon of power that equals, and in some ways exceeds the Promoted Field.
MYTH: Getting the value of a Distinguished Field requires loading the entire message into memory.
The first myth we need to dispel is that the Promoted Field is quicker to access than the Distinguished Field.
This is due to the statement in the old BizTalk Documentation (now deprecated but still possible to retrieve), and I quote:
One of the benefits of promoted Fields is that the value of the element that is promoted is available in the context of the message. This means that retrieving that value is inexpensive, as it does not require loading the message into memory to execute an XPath statement on the message.from The BizTalk Server Message.
What is implied here is that for the Promoted Field reading, its value doesn’t require an XPath read into the message and, conversely, that the Distinguished Field does require loading the message and has a performance cost because it’s evaluated when queried.
Nothing could be further from the truth! In fact, both the Promoted and Distinguished Fields are evaluated at the same time, and both are placed in the message context at the same time. So, let’s talk about how fields get into the message context.
… Lots of stuff cut out…
Since Distinguished fields do not require a separate property schema, the evaluation of Distinguished fields by the Orchestration engine consumes less overhead than the evaluation of Property fields by the Orchestration engine. The evaluation of Property fields requires an XPath query, the evaluation of Distinguished fields does not require an XPath query as the pipeline disassembler populates the Distinguished fields in the context and the orchestration engine gets the cached values. However, if the orchestration engine does not find the property in the context, it will then evaluate the XPath query to find the value. Distinguished fields do not have a size limitation.from About BizTalk Message Context Fields
Now, how does Promoted and Distinguished Fields get into the Message Context? This occurs automatically in the Receive Pipeline by specific pre-built pipeline components?
Out of the box, the BizTalk XML Disassembler, BizTalk Flat File Disassembler, and the BizTalk Framework Disassembler Promote Fields to the message context. All other production level Pipelines promote fields, most also support Distinguished Fields.
Distinguished Fields are written to the Message Context if one of these Receive Pipeline Components is used in the Pipeline. Interestingly enough, this explains why the Passthrough pipeline doesn’t promote Fields from the message. There are no components in the Passthrough Pipeline, it does nothing to the message content and therefore, nothing gets promoted, especially BTS.MessageType.
Regarding performance, Distinguished Fields beat out Promoted Fields 9 days each week. This is because both Promoted and Distinguished require the same overhead of writing the message value to the context Field bag in the Message Box. Still, Promoted Fields have the additional overhead of both being written to the Message Box context database AND the Subscription database. Promoted Fields have an impact every time a message is written to the Message Box because each Promoted Field that exists must be evaluated in a massive union (very efficiently written union, mind you!) that builds the list of matching activation subscriptions. So, in short, the more Promoted Fields that you have, the costlier the subscription process.
RECOMMENDATION: Use Promoted somewhat sparingly. Don’t avoid them, but do not use them if you do not need to. Use Promoted Fields as they were designed: to facilitate message routing, but not to make it easy to access a message value. Instead, primarily use Distinguished Fields.
MYTH: It’s always safe to use a Promoted or Distinguished Field in an Orchestration.
exists test for the existence of a message context property BTS.RetryCount exists Message_Infrom Using Operators in Expressions
Let us talk about how to handle message content that is missing when it is a Promoted Field and a Distinguished Field. What we are talking about specifically is the field that was Promoted, or Distinguished did not exist in the inbound message. The XLANG/s xpath statement that was used to query the message for the content during pipeline processing returned a null object.
The first thing to understand is when a Promoted and Distinguished Field comes into existence. They are essentially the same, and this occurs when a Pipeline component parses a message and either Promotes or Writes the value to the context. The simple answer is that when the value does not exist, the Field is not created. A query to the context for the Field returns a null object.
So, if you attempt to access a Promoted or Distinguished Field that didn’t exist in the inbound message, you can cause an unhandled exception to be thrown. Specifically, in both cases, a NullReferenceException.
Promoted Fields have a special XLang/s test operator: exists (we will soon blog about this operator). You can use this operator to determine if they exist before attempting to use them. In this case, Promoted Fields can always be tested for existence before use and can safely be avoided when they don’t exist.
Unfortunately, Distinguished Fields don’t have such a special test operator, and can cause an unpreventable unhandled exception. Specifically, if you use a Field that the underlying type is a native non-nullable type. For instance, suppose the value that you have distinguished is an integer. Integers cannot be null (and yes, I am aware of the Nullable<T> generics, but we are talking about what BizTalk XLANG/s has, not what is C# has), and if the underlying value didn’t exist, and you attempt to use the value, or even test to see if the value exists will cause an unhandled NullReferenceException when BizTalk’s XLang engine attempts to convert a null value into an integer by calling the System.Number.Parse(string) method with a null value.
Here comes in the kicker and why a Distinguished field can appear to be fine at design time but bite you at run-time.
At design time, the expression editor generates a pseudo-class-like dotted object for you to use in your expression. At run-time, there is simple type-casting that occurs by the run-time engine that inspects the XML datatype of the node in the Schema, retrieves the value as an object… then attempts to call the appropriate ConvertTo method on the Object. When casting a Null to an Int32 or any other intrinsic datatype, a NullReferenceException is thrown, and the Orchestration fails.
The primary difference (excluding Routing) between Promoted and Distinguished Fields is the developer’s design-time experience. Distinguished Fields are easy to use because they emulate .Net Class dotted notation.
RECOMMENDATION: If there is any chance that accessing the Distinguished Field may cause an exception, then place the check in a Scope Shape that has a catch shape to handle the NullReferenceException.
MYTH: Distinguished Fields are only accessible in Orchestrations
WRONG Documentation: Property Schemas
RIGHT Documentation: Distinguished Fields in Disassembler Pipeline Components, Processing the Message, Promote Properties (Node Property of All Schemas)
Another major fallacy about Distinguished Fields is that they are only accessible in the Orchestration. This is also untrue. The BizTalk Server Documentation clearly has an example of how to use Distinguished Fields in any component from the RIGHT Documentation above.
All Distinguished Fields outside of an Orchestration use a fixed schema:
The Field to use is the XPath of the node that is Distinguished, such as:
/*[local-name()='PO' and namespace-uri()='http://SendHtmlMessage.PO']/*[local-name()='Price' and namespace-uri()='']
Thus, to access this, you would use the Read Method:
MyObject = MyMessageContext.Read("/*[local-name()='PO' and namespace-uri()='http://SendHtmlMessage.PO']/*[local-name()='Price' and namespace-uri()='']", " http://schemas.microsoft.com/BizTalk/2003/btsDistinguishedFields”);
If the Field exists, then MyObject will contain an object that can be cast to the appropriate type.
RECOMMENDATION: Once the proper Pipeline Component has processed the message, use the Distinguished Field as you would any Field without the Xpath lookup overhead.
MYTH: Distinguished Fields in Orchestration Expression shapes are actually code.
You have to hand it to the people who did the coding for XLANG/s. It looks like C#, it feels like C#, and 99% of the time, it pretty much generates standard C#.
In many ways, this is not your father’s C#. It is really XLANG/s, and it has its own syntax and special components. Distinguished Fields are a prime example.
Think back on all the times you used a distinguished Field. It feels like it’s a C# Object! It uses dotted notation (Node.Node.Node.Attribute). You assign values to it, you use its value in an expression, and it comes out as the correct type. When the node is Boolean, then it behaves like a Boolean. Nothing could be further from the actual behavior. Just because it looks like a duck, doesn’t mean that it’s a duck. It really is a trick, that the Expression Editor parses the XSD on the fly and generates a classlike editor experience, but no actual code ever gets generated.
Hope you find this helpful! So, if you liked the content or found it helpful and want to help me write more content, you can buy (or help buy) my son a Star Wars Lego!