Building and applying reusable schema components
Schemas in BizTalk Server 2009 can be built to support reusability in a variety of ways. Let's look at four of them.
If I want to put the content of one schema into the definition of another, I can either import or include it. When the target namespace between the schemas differs, then the import
option must be used. For example, let's say that we design a schema
which represents a subject (or patient) that is planning to enroll in a
Next, we have a basic Enrollment schema that looks like this:
If we click the uppermost node named<Schema> in the Enrollment schema, we get a set of global settings available in the Visual Studio.NET Properties window. Select the ellipse next to the Imports property to launch the schema selection pane. Clicking the Add button will allow us to pick which schema in our project (or referenced projects) we wish to import. After selecting the Subject schema, and before clicking Ok on the pop up, we can see the namespace prefix and action that we're about to perform.
the import is complete, our schema tree view should look no different.
However, if we glance at the XSD schema view pane, we can see a new<xsd:import> command injected at the top of the schema.
How do we exploit this imported schema? Let's create a new record in the Enrollment schema. The Properties window for that node includes an attribute called Data Structure Type. Notice that we now have a ns1:Subject available as a data type.
Choosing the Subject data type causes the previously created Record to be replaced with the full Subject schema structure from our other schema.
Note that any changes made to the imported schema are automatically reflected in the master schema.
If the schema you wish to reuse is in the same namespace as the master schema, then you have to perform a schema include.
Including one schema in another is fairly similar to the import
procedure. Before this exercise, I updated the schemas so that the Enrollment and Subject schemas reside in the same namespace. We once again highlight the<Schema> node in the Enrollment schema and choose Imports from the Properties window. Be sure to change the value in the drop-down list from the default value, XSD Imports, to XSD Includes. Notice that after picking the Subject schema again the Namespace and Schema values match the default namespace of the master schema.
The source of the Enrollment XSD file now includes an XML<xsd:include>
statement pointing to the included schema. That's not the only
difference from the Import operation. Notice that the schema tree now
has a ghosted Subject node at the top of it. We can now create a new record under the Enrollment node and point the Data Structure Type to Subject.
working with included schemas, you may experience some unexpected
behavior when generating XML instances for the schema. As the schema
above stands, if I choose to Generate Instance, the Subject node will be the one generated as the root node, not the expected Enrollment element. The way to get around this is to click the uppermost<Schema> node, choose the Root Reference property, and explicitly define Enrollment as the root of the schema.
In the off chance that you wish to use another schema, and make a variation to it, then this is where the redefine
option comes in. In this scenario, you reference a schema (in the same
namespace) and you have the option of making modifications to it. You
need to be cautious with redefinitions as you break your connection to
the original schema.
final type of schema reuse comes into play when designing global types
that can be employed by other schemas. So far we've seen reuse of
entire schemas, but what if we have a set of standard types that by themselves are not standalone messages, but instead are snippets of data structures? For instance, let's take an address address type and use that in all our relevant schemas.
as an example. A typical address structure exists in all sorts of
schema types and is probably duplicated over and over again. We could
define a global
We can do this by first creating a new schema and defining a record that outlines the Address structure.
Next, we click the record name, select the Data Structure Type property, and manually type in a value such as AddressType. The Schema Editor now reflects the construction of a new global type.
The next thing to do is actually delete the Address node. Why is that? Because we don't actually need or want the element of the AddressType
in this schema. All we actually want is the type declaration, which
survives after the record is deleted. Our schema now shows no nodes in
the tree, but we can see within the XSD that a global type exists.
If we import this schema in our Subject schema (which we have to do because they are in different namespaces), and create a new record called Addresses, we can now choose AddressType as the Data Structure Type for this record.
As you would hope, the relationship between the Subject and Address is retained even when the Subject is imported into the Enrollment schema. We've daisy chained three schemas in a very reusable way.
Finally, what's the impact of using imports/includes/redefines in your BizTalk-generated WCF endpoints? All three are supported by the BizTalk WCF Service Publishing Wizard. However, service consumers may experience issues when a schema possesses a redefine
command, so use that with caution. Even with multiple nesting of
included schemas, the WCF svcutil.exe had no problem interpreting the
contract. However, this is an area where interoperability can be a
problem. As a best practice, try to limit excessive schema reuse if you
cannot be sure of the types of clients consuming your service.