A tag is a keyword associated with an object stored in StateServer. You can associate tags with objects, remove tag associations from objects and test for the presence of a tag on an object by using the extension methods defined in TagExtensions. Once a tag or set of tags have been associated with an object, the tags are stored as part of the object state and are also stored in the property index for the the object so that searches for objects with a given set of tags can occur on the server. This section provides an overview of how to use tags in the StateServer environment.
To associate tags with objects stored in a NamedCache, the object's type must implement the ITaggable interface. This interface requires an implementation that creates a well-known property, TagHolder, in the implementing object that the NamedCache's tag implementation uses to store a bitmap representing the tags associated with the object. Other than declaring the property, the implementating object does not need to supply any behavior in support of the object. Management of the tags is automatic and handled by the NamedCache subsystem.
The set of strings used as tags on objects is scoped by the NamedCache in which the objects are stored. Whenever you associate a tag with an object, the NamedCache checks to see if the tag is known within a tag dictionary managed by the object's NamedCache. If not, the tag is added to the dictionary which is then published via StateServer so that update is available to all servers in the server farm.
The TagExtensions extension methods such as AddTags and RemoveTags must, therefore, be able to access the NamedCache that a tagged object will be written to so it has access to the appropriate tag dictionary when adding, removing, or testing tags. The second property required by the ITaggable, interface, NamedCache, provides that access.
The Product class below implements ITaggable.
[Serializable] class Product : ITaggable { private static readonly NamedCache _namedCache = CacheFactory.GetCache("ProductCache"); SparseBitmap ITaggable.TagHolder { get; set; } NamedCache ITaggable.NamedCache { get { return _namedCache; } } public string Name { get; set; } public decimal Price { get; set; } }
The implementation for TagHolder is just a compiler-generated getter/setter. The NamedCache implementation simply returns the NamedCache, instance cached in the static initializer.
Since the Product class defined in the previous section implements ITaggable, we can use Product instances with the extension methods in TagExtensions. For example, here we create three Product instances and associate each of them with a set of tag values by using the AddTags method.
Product p1 = new Product() { Name = "Beanbag Cellphone Chair", Price = 9.99m }; p1.AddTags("Gadget", "cellphone", "cellphone stand"); Product p2 = new Product() { Name = "Keychain Speaker Amp", Price = 9.99m }; p2.AddTags("Gadget", "cellphone", "audio"); Product p3 = new Product() { Name = "JuiceBar Portable Solar Charger", Price = 49.99m }; p3.AddTags("Gadget", "cellphone", "charger", "solar");
We can test objects to see if all tags in a specified list are present on an object by using the HasAllTags method like this:
bool t = p1.HasAllTags("Gadget", "cellphone"); // true bool f = p1.HasAllTags("Gadget", "cellphone", "audio"); // false
Similarly, we can test objects to see if any tags in a specified list are present on an object using the HasAnyTag method like this:
bool t = p2.HasAnyTag("apples", "oranges", "audio"); // true bool f = p2.HasAnyTag("apples", "oranges", "bananas"); // false
We can test to see that certain tags are present while at the same time certain tags are missing by using the HasTags method like this:
string[] mustBePresent = { "Gadget", "audio" }; string[] mustBeMissing = { "solar" }; bool p1HasTagsTest = p1.HasTags(mustBePresent, mustBeMissing); // false bool p2HasTagsTest = p2.HasTags(mustBePresent, mustBeMissing); // true bool p3HasTagsTest = p3.HasTags(mustBePresent, mustBeMissing); // false
Note |
---|
The HasAllTags, HasAnyTag, and HasTags methods may also be used in LINQ where clauses in which case the methods are executed remotely on the server. See Querying Tags for more details. |
We can enumerate the set of tags currently associated with an object by using the GetTags method like this:
foreach (string tag in p3.GetTags()) { Console.WriteLine(tag); }
You can remove a tag association from an object with the RemoveTags method like this
// Remove specified tags from the object - they don't have to exist // on the object p2.RemoveTags("Gadget", "oranges");
To remove all tags from an object, you can combine GetTags with RemoveTags like this:
// Remove all tags on an object
p2.RemoveTags(p2.GetTags());
The strings used in tag operations are case-independent. If isGadget is true aftre executing the following example, then isStillGadget will be false.
bool isGadget = p1.HasAllTags("Gadget"); p1.RemoveTags("gadget"); bool isStillGadget = p1.HasAllTags("Gadget");