A few things you didn't know about Commerce Server's Catalog Cache

One of the most important aspect of any e-commerce is their Catalog(s) and Commerce Server provides a system that allows customers to manage and organize their products. In any e-commerce site the most profile usage the Catalog. Searches and Catalog browsing constitutes about 70 percent or more of a site. Performance becomes an issue when you have to make that many round trip calls to the database. In order to minimize this you have to provide some mechanism for caching. Well as it happens Commerce Server's Catalog System has such a caching system.

Catalog Cache

Commerce Server's Catalog Cache is a lazy cache. If caching is turned on under the web.config in runtime scenarios then any request made is checked, if caching is on then we look into the cache and see if the object exists if not then a request is made to the database and the object is cached before returned to the caller.

Web.config Settings

The table below shows the cache settings for a Commerce Server site.

<catalog>    <catalogSets defaultAnonymous="Anonymous User Default CatalogSet" defaultAuthenticated="Registered User Default CatalogSet"/>    <cache enable="true" schemaTimeout="10" itemInformationCacheTimeout="10" itemHierarchyCacheTimeout="10" itemRelationshipsCacheTimeout="10" itemAssociationsCacheTimeout="10" catalogCollectionCacheTimeout="10"/></catalog>

As you can see caching is enabled and there are five items that can be cached. Instead of me explaining this which is already documented how about you do a bit of leg work. You can find more detailed info about these settings as well as the CacheConfiguration object here. Each item has a timeout period after which the item is dropped from cache.

Refreshing the Cache

Catalog Cache can be refreshed by using Catalog Manager, Staging Services or hitting a specific URL. This URL is protected and by default only administrators can access it. The URL is an httpHandler and this setting can also be found at the web.config.

<httpHandlers>    <add verb="*" path="SiteCacheRefresh.axd" type="Microsoft.CommerceServer.Runtime.SiteCacheRefresh, Microsoft.CommerceServer.Runtime, Version=6.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35 "/></httpHandlers>

To add an account that accesses this URL you must do so under the web.config.

<location path="SiteCacheRefresh.axd">    <system.web>        <authorization>            <allow roles="BUILTIN\Administrators"/>            <allow roles="VORDEFINIERT\Administratoren"/>            <allow roles="BUILTIN\Administrateurs"/>            <deny users="*"/>            <deny users="?"/>        </authorization>    </system.web></location>

Cache Size

Commerce Server's Catalog items are typed DataSets and can be as large as 300KB per item. If you have a large Catalog the cache size can grow pretty big. To minimize this you can set the Cache Timeout to a smaller amount like 10 minutes. If I remember correctly this is the number of minutes that we tested the Commerce Server's Catalog Performance.

Where is the Cache?

Commerce Server utilizes ASP.NET cache. The following code will dump all the cache keys.

foreach (DictionaryEntry key in Cache){    Response.Write(key.Key.ToString());    Response.Write("<br />");}

The following is the cache out put from Starter Site.

CS2007TRAINING,StarterSite_productcatalog,dbo.ctlg_GetCatalogsInCatalogSetByName,Registered User Default CatalogSetCS2007TRAINING,StarterSite_productcatalog,dbo.ctlg_GetCatalogLanguages,Adventure Works CatalogCS2007TRAINING,StarterSite_productcatalog,dbo.ctlg_GetCatalogsInCatalogSetByName,Anonymous User Default CatalogSetCS2007TRAINING,StarterSite_productcatalog,dbo.ctlg_GetParentCategories,Adventure Works Catalog,Adventure Works Catalog,en-US,14,*,FalseCS2007TRAINING,StarterSite_productcatalog,dbo.ctlg_GetPropertiesInCatalog,Adventure Works CatalogCS2007TRAINING,StarterSite_productcatalog,dbo.ctlg_GetProductOIDAndType,Adventure Works Catalog,AW099-15,en-US,,,,,,ctlg_QueryCatalogInfo|Adventure Works Catalog|AW099-15||en-USCS2007TRAINING,StarterSite_productcatalog,dbo.ctlg_GetPropertyAttributes,IntroductionDateCS2007TRAINING,StarterSite_productcatalog,dbo.ctlg_GetDefinitions,,Crampon,CS2007TRAINING,StarterSite_productcatalog,dbo.ctlg_GetProductProperties,Adventure Works Catalog,False,14,ProductCode,VariantCode,Adventure Works Catalog,en-US,NoJoin,,,,P.BaseCatalogName,CategoryName,P.oid,DefinitionName,IsSearchable,cy_list_price,UseCategoryPricing,i_ClassType,CatalogName,ProductId,OrigProductId,VariantId,OrigVariantId,PrimaryParentCategory,DisplayName,Timestamp,OriginalPrice,LastModified,ParentOId,True,,,False,False,False,True,False,0CS2007TRAINING,StarterSite_productcatalog,dbo.ctlg_GetCatalogGlobalProperties,Adventure Works Catalog,en-USCS2007TRAINING,StarterSite_productcatalog,dbo.ctlg_GetPropertyAttributes,TestCS2007TRAINING,StarterSite_productcatalog,dbo.ctlg_GetPropertyAttributes,Image_filenameCS2007TRAINING,StarterSite_productcatalog,dbo.ctlg_GetRootProducts,Adventure Works Catalog,en-US,False,NoJoin,,,, [CategoryName],[ProductID],[CatalogName],[i_ClassType],[DisplayName],[cy_list_price],[BaseCatalogName],[oid],[OrigProductId],[DefinitionName],[PrimaryParentCategory],[UseCategoryPricing],1,10,,True,0,True,,,False,False,False,True,False,0,*CS2007TRAINING,StarterSite_productcatalog,dbo.ctlg_GetPropertyAttributes,Image_heightCS2007TRAINING,StarterSite_productcatalog,dbo.ctlg_GetCategoryOID,Adventure Works Catalog,,en-US,,,,CS2007TRAINING,StarterSite_productcatalog,dbo.ctlg_VC_BC_GetDependentCatalogs,Adventure Works Catalog,1,2147483646,,True,0,en-USCS2007TRAINING,StarterSite_productcatalog,dbo.ctlg_GetPropertyAttributes,ProductCodeCS2007TRAINING,StarterSite_productcatalog,dbo.ctlg_GetCatalogSetInfoByName,Registered User Default CatalogSetCatalogHelper.CatalogsForAnonymousUserCS2007TRAINING,StarterSite_productcatalog,dbo.ctlg_GetPropertyAttributes,Image_widthCS2007TRAINING,StarterSite_productcatalog,dbo.ctlg_GetCategoryOID,Adventure Works Catalog,,en-US,,,False,FalseCS2007TRAINING,StarterSite_productcatalog,dbo.ctlg_GetCatalogProperties,Adventure Works Catalog,en-US,,CS2007TRAINING,StarterSite_productcatalog,dbo.ctlg_GetRootProducts,Adventure Works Catalog,en-US,False,NoJoin,,,,*,1,2147483646,,True,0,True,,,False,False,False,True,False,0,*CS2007TRAINING,StarterSite_productcatalog,dbo.ctlg_GetPropertyAttributes,OnSaleCS2007TRAINING,StarterSite_productcatalog,dbo.ctlg_GetRootCategories,Adventure Works Catalog,en-US,False,*,1,2147483646,,True,0CS2007TRAINING,StarterSite_productcatalog,dbo.ctlg_GetCategoryProperties,Adventure Works Catalog,-1,Adventure Works Catalog,en-US,BaseCatalogName,CategoryName,OrigCategoryName,oid,DefinitionName,IsSearchable,cy_list_price,UseCategoryPricing,i_ClassType,CatalogName,ProductId,OrigProductId,VariantId,OrigVariantId,PrimaryParentCategory,DisplayName,Timestamp,OriginalPrice,LastModified,ParentOId,FalseCS2007TRAINING,StarterSite_productcatalog,dbo.ctlg_GetCatalogProperties,Adventure Works Catalog,,,CS2007TRAINING,StarterSite_productcatalog,dbo.ctlg_GetCatalogSetInfoByName,Anonymous User Default CatalogSetCS2007TRAINING,StarterSite_productcatalog,dbo.ctlg_GetDefinitionProperties,Crampon,CS2007TRAINING,StarterSite_productcatalog,dbo.ctlg_GetPropertyAttributes,ProductSize

So here is something you may not have known

When you add an item to basket and execute the basket pipeline component there are two components that interact with the Catalog System QueryCatalogInfo and RequiredProdInfo. The QueryCatalogInfo is also dependant upon the cache values under the web.config. Why is that? The QueryCatalogInfo checks to make sure that the lineitems are in synch with the Catalog System and if not then marks them as deleted and the RequiredProdInfo removes the lineitem from the basket. The QueryCatalogInfo also keeps a cache of it's own separate from sites items cache. This increases the cache size and the same cache configuration values under the web.config are applied to the QueryCatalogInfo component cache.

As you can see there are two processes that depend on one configuration setting. under the "Where is the cache?" section in the second table, notice the red text that defines the QueryCatalogInfo cache item.

How to decouple this Configuration

There maybe scenarios that you will need to disable the Commerce Server's Cache as you may have implemented your own caching mechanism. Which means that by disabling the Commerce Server's Catalog Cache you will suffer performance hit in the checkout process.

The CacheConfiguration is passed as a context to the pipeline component so it's possible to disable the web.config Cache and create your own pipeline component that sets a cache settings for the QueryCatalogInfo component. Just make sure that this component is placed before the QueryCatalogInfo component.

The following code enables you to set your own cache settings.

public int Execute(object pdispOrder, object pdispContext, int lFlags)

{

CacheConfiguration cacheConfig = new CacheConfiguration();

    cacheConfig.CacheEnabled = true;

    cacheConfig.ItemInformationCacheTimeout = 10;

    ((IDictionary)pdispContext)["CatalogCacheConfiguration"] = cacheConfig;

return 1;

}

 

 This post was done with consultation of Ben Taylor from Shape Factory LTD in UK.