Partilhar via


Tagging Objects in the AppFabric Cache

In two of my previous entries I outlined functionality and patterns used in the AppFabric Cache.  In this entry I wanted to expand and look at another area of functionality that people have come to expect when working with cache technology. 

This expectation is the ability to tag content with more information than just the key.  As you start to examine this expectation you will soon find yourself asking if the tagged data can be related to each other and finally if it is possible to remove the related data.

One of the nice things about the AppFabric Cache is that it is so easy to work with and can be so simple.  Then, if needed, like with this topic, you can take advantage of the addition functionality.  This is where the real benefits of AppFabric Cache come into play over the other cache alternatives.

Lets take a deeper look at tagging.  Tagging is essentially assigning one or more string values to an object contained in the cache.   The object in the cache can then be retrieved by using the tag or multiple tags.   When you tag an object, all of the tagged objects will reside within a region.  A region is an additional container inside the cache.  Because regions are optional, if you want to use them you need to explicitly create them at runtime within your application code.  You can setup different regions for different types of related data.  When you utilize regions, you have the option to retrieve all objects in that region and therefore by default have setup a solution that now provides you access to all the dependent data.  We can take this one step further in that you can also delete all of the data within a region and not have to worry about looping through all entries to find the specific keys and their dependencies.

As an example we could create a region called 'Beverages' and then we could cache all of the beverages we sell and tag each item by the type of beverage such as Soft Drink, Wine, Beer.  We could even go one step further and provide multiple tags so that we could further segment the Wine category into White or Red or Merlot, Zinfandel, Riesling, etc.  At this point the application could retrieve all of the catalog items based on the search criteria that were entered.

Lets look at how we can setup the region and tags.  We will also look at the methods that are available to interact with objects using tags and lastly, how we can manage the data in the cache; adding, retrieving and deleting.

Setting Up a Region:

The code that follows assumes that you already now how to create a cache (either through code or through the PowerShell cmdlets (as found in my previous post here)).

To create a region we already need to have the cache created.  Once that is done, we can pass in the cache name, use the GetCache method and then call the CreateRegion method passing in a region name.  We can create as many regions as we need based on the manner in which you wish to segment the data.  One thing to keep in mind however is that there can be performance implications when using regions.  The code below shows how we can create the region.

private void CreateRegion(string CacheName, string RegionName)
{

    //This can also be kept in a config file
    var config = new DataCacheFactoryConfiguration();
config.Servers = new List<DataCacheServerEndpoint>
{
            new DataCacheServerEndpoint(Environment.MachineName, 22233)
};

    DataCacheFactory dcf = new DataCacheFactory(config);

    if (dcf != null)
{
        var dataCache = dcf.GetCache(CacheName);
dataCache.CreateRegion(RegionName);
}
}

 Now that we have a cache with a region created lets look at the methods that are available to interact with tags

Methods to work with tagging (from MSDN):

Method Description

GetObjectsByTag

Provides a simple way to access objects that contain tags (exact match, intersection, or union). The region name is a required parameter.

GetObjectsByAnyTag

Returns a list of objects that have tags matching any of the tags provided in the parameter of this method.

GetObjectsByAllTags

Returns a list of objects that have tags matching all of the tags provided in the parameter of this method.

GetObjectsInRegion

Returns a list of all objects in a region. This method is useful when you do not know all the tags used in the region.

GetCacheItem

Returns a DataCacheItem object. In addition to the cached object and other information associated with the cached object, the DataCacheItem object also includes the associated tags.

Add

When adding an object to cache, this method supports associating tags with that item in the cache.

Put

When putting an object into cache, this method can be used to replace tags associated with a cached object.

Remove

This method deletes the cached object and any associated tags.

Managing the data in the cache

There are a number of methods to get objects out of the cache but logically I like to start in terms of adding to the cache first.  So, lets take a look at the put method.  The put method will update an object that already has a key that is contained in the cache (whereas the Add will return an exception if the key is already present).  The put method can also update or add new tags to an existing object in the cache.  As we look at the Put method signature below we can see that this version of the method accepts the key and value just as the other overrides of the Put method do but this one also adds on a collection of tags as well as the name of the region that the cached item will reside in.

public DataCacheItemVersion Put (
string key,
Object value,
IEnumerable<DataCacheTag> tags,
string region
)

The code below shows how we can use the Put method and include multiple tags

private void InsertCacheObjectWithTag(string CacheName, string RegionName)
{
    //This can also be kept in a config file

    var config = new DataCacheFactoryConfiguration();
config.Servers = new List<DataCacheServerEndpoint>
{
        new DataCacheServerEndpoint(Environment.MachineName, 22233)
};

    DataCacheFactory dcf = new DataCacheFactory(config);

    if (dcf != null)
{
        List<DataCacheTag> tags = new List<DataCacheTag>
{
                new DataCacheTag("Wine"),
                new DataCacheTag("Red"),
                new DataCacheTag("Merlot")
};

        var dataCache = dcf.GetCache(CacheName);

dataCache.Put("WineKey", "WineValue", tags, RegionName);
}
}

Now we can look at the methods to retrieve objects.  There are four main Get methods.  We can get by tag, any tag, all tags and finally any object that exists in the region no matter what tag.  The GetObjectsInRegion method is what provides us the ability to implement a scenario in which all cached objects are related and can be treated as a group.  The related data can also be removed by called dataCache.RemoveRegion(RegionName) just as we called the CreateRegion method above.

For people that have been working with Memcached you can delete dependent data through the cas (check and set) operation.  The reason that I bring this up is that more people are familiar with Memcached and therefore I am asked if AppFabric Caching has this or that functionality.  What I am finding is that it has the same functionality and more.  It is just implemented a bit differently.

Anyways, if we want to retrieve all the objects in the cache that have a Wine tag we can use the GetObjectsByTag as shown below:

public IEnumerable<KeyValuePair<string, object>> GetLookUpCacheDataByTag(string TagValue)
{
    var config = new DataCacheFactoryConfiguration();
config.Servers = new List<DataCacheServerEndpoint>
{
            new DataCacheServerEndpoint(Environment.MachineName, 22233)
};

    DataCacheFactory dcf = new DataCacheFactory(config);

    var cache = dcf.GetCache(cacheName);

    DataCacheTag dct = new DataCacheTag(TagValue);

    return cache.GetObjectsByTag(dct, regionName); //regionName could either be passed in or an internal variable
}

and lastly, we can remove items based on a tag.  I already mentioned that we can call the RemoveRegion method to remove all the related data that is grouped together in a region.  If there is a specific item that you want removed then you can call the Remove method and pass in the key.  If you wanted to delete based on a tag value then you would have to call one of the GetXXX methods, obtain the key, and then call the Remove method by passing the returned key value.