I prefer not to use the native XRef option because the values are hidden away in the BizTalk schema, are cumbersome to load, and are only available to BizTalk maps. A custom cross-reference implementation is fairly trivial, can be made available to any .NET consumer, and you can control what gets cached and how long the cache lives.

The problem with using a static dictionary is that it lives for the duration of the app domain – so the lookup values will be used for every run of the map until the BizTalk host instance is restarted. This is also true for the native Xref cache. Removing stale cache items becomes a manual process, liable to be forgotten.

In a custom implementation you can automate flushing the cache. Monitoring the data source and flushing when it changes is an expensive option, but a cheap alternative is to store the expected lifespan of the cache in configuration, so when the cache reaches the configured age it flushes itself:

<x.y.z.integration.maps>

<caching>

<cachekey="StatusCodeLookup"lifespan="P1D"/>

<cachekey="CustomerLookup"lifespan="PT10M"/>

</caching>

</x.y.z.integration.maps>

Returning the lookup value then falls into three parts – flush the cache if expired, check the cache, get from source and add to cache if not already present:

Full sample on github here: ConfigurableCrossReferenceCache. (This snippet omits logging and error handling for brevity, but in the sample there's plenty of both, which makes building and monitoring your cache much easier).