Querying Tags

ScaleOut Software NamedCache API

In addition to boolean expressions terms consisting of boolean properties and comparison operators, StateServer can also process Tag expressions when evaluating LINQ where clauses. Tags are arbitrary strings that are explicitly associated with objects to create groupings of objects. Tagging objects provides a way to help describe the object and allows it to be more easily found by querying for a tag or tags. This section provides an overview of using Tags in LINQ where clauses.

The ITaggable Interface

To associate Tags with objects stored in a NamedCache, the object's type must implement the ITaggable interface. This interface primarily creates a well-known property in the object that the Tag implementation uses to store the tags associated with the object. Management of the Tags is automatic and handled by the NamedCache subsystem.

For example, consider the class:

[Serializable]
class BlogEntry : ITaggable
{
    public string Title { get; set; }
    public string Content { get; set; }

    SparseBitmap ITaggable.TagHolder { get; set; }
    NamedCache ITaggable.NamedCache
    {
        get { return CacheFactory.GetCache("BlogData"); }
    }
}
BlogEntry implements the interface ITaggable using just a default implementation of the TagHolder property. In this case, BlogEntry implements the ITaggable interface explicitly. However, we could also have implemented the interface with public properties. The TagHolder property has the SossIndexAttribute set in the interface definition itself. Consequently, the TagHolder implementation within BlogEntry is implicitly treated as if it carried the SossIndexAttribute.

The NamedCache property simply looks up the NamedCache in the CacheFactory given the application name "BlogData". Alternatively, the NamedCache. instance could simply be cached in a static field and the property implementation could return the cached instance.

Adding Tags to an Object

Next, we create a BlogEntry instance and add some tags. Note that the tags are held in the object itself and are written along with the object when the object is stored in the cache. If these tag strings are not already in use within this NamedCache, they will be automatically distributed around the system to all other StateServers as a side effect of adding the tags to this object.

NamedCache cache = CacheFactory.GetCache("BlogData");
BlogEntry blogEntry = new BlogEntry()
{
    Title = "Why Tags Are Cool",
    Content = "<html>... blah blah ...</html>"
};

blogEntry.AddTags("Tags", "StateServer", "Samples", "Cool Things");
cache[Guid.NewGuid()] = blogEntry;    // write blogEntry out to the cache

Testing Tags in a Where Clause

We can query out all BlogEntry instances that have both of the tags "Cool Things" and "Samples" set with code like this:

var coolSamples = from b in cache.QueryObjects<BlogEntry>()
                  where b.HasAllTags("Cool Things", "Samples")
                  select b;

string aCoolSampleTitle = coolSamples.First().Title;
The method HasAllTags is evaluated on the StateServer instances in the server farm. The BlobEntry instances that have the specified tags set are returned to the client where they are enumerated.

In addition to HasAllTags, StateServer also supports the HasAnyTag and HasTags methods in LINQ where clauses.

The methods mentioned above may also be used outside the context of a LINQ where clause. For example, if we wanted to check on the client that an object returned from the above query also had the tags "Tags" and "StateServer" associated with it we could write code like this:

// get a BlogEntry from somewhere...
BlogEntry someBlogEntry = coolSamples.First();

// Test the in-memory instance ...
if (someBlogEntry.HasAllTags("Tags", "StateServer")) {
    // this blog must be about StateServer Tags
}

See Also

Reference

Other Resources