Sets Behavior and Usage in Cache
Note
This feature is only available in NCache Enterprise Edition.
A HashSet in NCache is an unordered data type which does not contain duplicate values. For example, a HashSet can be used to store the customer IDs of all users logging into a e-commerce site in a given day. If the user logs in again, the ID is not stored again as duplicate values are not allowed. NCache further enhances this HashSet by providing NCache specific features such as expiration, dependency, groups and more to the HashSet.
Behavior
- Only primitive types are supported for sets.
- Null is not a valid type.
- Sets can not contain duplicate values.
- Sets are named; you need to provide a unique cache key for each set.
Pre-requisites
- Install the following NuGet packages:
- Include the following namespaces in your application:
Alachisoft.NCache.Client
Alachisoft.NCache.Client.DataTypes
Alachisoft.NCache.Client.DataTypes.Collections
Alachisoft.NCache.Runtime.Events
Alachisoft.NCache.Runtime.Exceptions
- The application must be connected to cache before performing the operation.
- Cache must be running.
- For API details, refer to: ICache, CreateHashSet, GetHashSet, GetRandom, Lock, RemoveRandom, Unlock.
- To ensure the operation is fail safe, it is recommended to handle any potential exceptions within your application, as explained in Handling Failures.
- To handle any unseen exceptions, refer to the Troubleshooting section.
Create and Perform Union on Default HashSets
The following code sample creates two HashSets of int type in cache using CreateHashSet
for users logging on Monday and Tuesday, and performs a union of those both sets into a third HashSet which ultimately stores unique user IDs of the whole week. It then gets random user IDs from the union set using GetRandom
.
Warning
A set can not contain duplicate values.
Tip
You can also configure searchable attributes such as groups/tags/named tags and invalidation attributes such as expiration/eviction/dependency while creating a data type.
try
{
// Pre-condition: Cache must be connected
// Create unique keys for hashSets
string MondayUsersKey = "MondayUsers";
string TuesdayUsersKey = "TuesdayUsers";
string WeeklyUsersKey = "WeeklyUsers";
// Create hashSets of object type
IDistributedHashSet<int> userSetMonday = cache.DataTypeManager.CreateHashSet<int>(MondayUsersKey);
// Add user IDs for Monday
userSetMonday.Add(1223);
userSetMonday.Add(34564);
userSetMonday.Add(3564);
IDistributedHashSet<int> userSetTuesday = cache.DataTypeManager.CreateHashSet<int>(TuesdayUsersKey);
// Add userIDs for Tuesday
UserSetTuesday.Add(4545);
UserSetTuesday.Add(34564);
UserSetTuesday.Add(3564);
UserSetTuesday.Add(7879);
// userSetMonday will contain unique values from both sets after union
userSetMonday.StoreUnion(MondayUsersKey, TuesdayUsersKey);
// Get 3 Random Users from set
int[] randomUsers = userSetMonday.GetRandom(3);
}
catch (OperationFailedException ex)
{
// NCache specific exception
if(ex.ErrorCode == NCacheErrorCodes.KEY_ALREADY_EXISTS)
{
// The specified key already exists in cache,
// Either remove the existing object from cache
// Or specify another key
}
else if (ex.ErrorCode == NCacheErrorCodes.CACHEITEM_IN_DATA_STRUCTURES)
{
// Data structures cannot be of CacheItem type
// CacheItems cannot be added in data structures
}
else
{
// Exception can occur due to:
// Connection Failures
// Operation Timeout
// Operation performed during state transfer
}
}
catch (Exception ex)
{
// Any generic exception like ArgumentNullException or ArgumentException
}
Recommendation: To ensure the operation is fail safe, it is recommended to handle any potential exceptions within your application, as explained in Handling Failures.
Fetch HashSet from Cache
You can fetch a set from cache using GetHashSet
, which takes a cache key as parameter. This key is the name of the set which is specified during set creation.
Warning
If the item being fetched is not of HashSet type, a Type mismatch
exception is thrown.
try
{
// Pre-condition: Cache is already connected
// HashSet with this key already exists in cache
string key = "ProductIDSet";
// Get hashset and show items of hashset
IDistributedHashSet<int> retrievedHashSet = cache.DataTypeManager.GetHashSet<int>(key);
if (retrievedHashSet != null)
{
foreach (var item in retrievedHashSet)
{
// Perform operations
}
}
else
{
// HashSet does not exist
}
}
catch (OperationFailedException ex)
{
// NCache specific exception
if (ex.ErrorCode == NCacheErrorCodes.NOT_A_HASHSET)
{
// Item being fetched is not of HashSet type;
// Cache key corresponds to an item of different data type
}
else if (ex.ErrorCode == NCacheErrorCodes.TYPE_NOT_ALLOWED)
{
// The object being fetched is not of primitive type
// Custom objects are not yet supported
}
else
{
// Exception can occur due to:
// Connection Failures
// Operation Timeout
// Operation performed during state transfer
}
}
catch (Exception ex)
{
// Any generic exception like ArgumentNullException or ArgumentException
}
Recommendation: To ensure the operation is fail safe, it is recommended to handle any potential exceptions within your application, as explained in Handling Failures.
Remove Items from Set
Items can be removed from a set either by specifying the item itself, or at random. The following code sample removes the users of Monday from the weekly users set which have already been added to cache. It then removes users at random from the weekly set as well using RemoveRandom
.
Tip
To remove the whole set from cache, refer to the Remove Data Structures From Cache page.
try
{
// Pre-condition: Cache must be connected
// Get existing HashSets
string UserIDMondayKey = "UserIDMonday";
string UserIDWeeklyKey = "UserIDWeekly";
IDistributedHashSet<int> userSetMonday = cache.DataTypeManager.GetHashSet<int>(UserIDMondayKey);
IDistributedHashSet<int> usersWeekly = cache.DataTypeManager.GetHashSet<int>(UserIDWeeklyKey);
// Remove users of Monday from Weekly set
usersWeekly.Remove(userSetMonday);
// Remove Random users from weekly set
userWeekly.RemoveRandom();
}
catch (OperationFailedException ex)
{
// NCache specific exception
if (ex.ErrorCode == NCacheErrorCodes.NOT_A_SET)
{
// Item being fetched is not of HashSet type;
// Cache key corresponds to an item of different data type
}
else if (ex.ErrorCode == NCacheErrorCodes.TYPE_NOT_ALLOWED)
{
// The object being fetched is not of primitive type
// Custom objects are not yet supported
}
else
{
// Exception can occur due to:
// Connection Failures
// Operation Timeout
// Operation performed during state transfer
}
}
catch (Exception ex)
{
// Any generic exception like ArgumentNullException or ArgumentException
}
Event Notifications on HashSets
You can register cache events as well as data type events on a data type such as set. For behavior, refer to the Feature Wise behavior topic.
The following code sample registers a cache event of ItemAdded
and ItemUpdated
as well as registers an event for ItemAdded
and ItemUpdated
on the set in cache.
Once a set is created in cache, an ItemAdded
cache level event is fired. However, once an item is added to set, an ItemAdded
data type event is fired, and an ItemUpdated
cache level event is fired.
Register Event on HashSet Created
try
{
// Pre-condition: Cache is connected
// Unique cache key for hashset
string key = "UserIDMonday";
// Create hashset
IDistributedHashSet<int> hashset =
cache.DataTypeManager.CreateHashSet<int>(key);
// Register ItemAdded, ItemUpdated, ItemRemoved events on hashset created
// DataTypeNotificationCallback is callback method specified
hashset.RegisterNotification(DataTypeDataNotificationCallback, EventType.ItemAdded |
EventType.ItemUpdated | EventType.ItemRemoved,
DataTypeEventDataFilter.Data);
// Perform operations
}
catch (OperationFailedException ex)
{
// NCache specific exception
// Exception can occur due to:
// Connection Failures
// Operation Timeout
// Operation performed during state transfer
}
catch (Exception ex)
{
// Any generic exception like ArgumentNullException or ArgumentException
}
Specify Callback for Event Notification
private void DataTypeDataNotificationCallback(string collectionName, DataTypeEventArg collectionEventArgs)
{
switch (collectionEventArgs.EventType)
{
case EventType.ItemAdded:
// Item has been added to the collection
break;
case EventType.ItemUpdated:
if (collectionEventArgs.CollectionItem != null)
{
// Item has been updated in the collection
// Perform operations
}
break;
case EventType.ItemRemoved:
// Item has been removed from the collection
break;
}
}
Locking HashSets
HashSets can be explicitly locked and unlocked to ensure data consistency. The following code sample creates a set and locks it for a period of 10 seconds using Lock() and then unlocks it using Unlock().
try
{
// Pre-conditions: Cache is already connected
// HashSet exists with key "UserIDMonday"
// Cache Key
string key = "UserIDMonday";
// Get hashset
IDistributedHashSet<int> hashset = cache.DataTypeManager.GetHashSet<int>(key);
bool isLocked = hashset.Lock(TimeSpan.FromSeconds(10));
if (isLocked)
{
// HashSet is successfully locked for 10 seconds
// Unless explicitly unlocked
}
else
{
// HashSet is not locked because either:
// HashSet is not present in the cache
// HashSet is already locked
}
hashset.Unlock();
}
catch (OperationFailedException ex)
{
// NCache specific exception
// Exception can occur due to:
// Connection Failures
// Operation Timeout
// Operation performed during state transfer
}
catch (Exception ex)
{
// Any other generic exception like ArgumentNullException or ArgumentException
}
Additional Resources
NCache provides sample application for Basic Operations on GitHub.
See Also
List Behavior and Usage in Cache
Queue Behavior and Usage in Cache
Dictionary Behavior and Usage in Cache
Using Counter in Cache
Configure Searchable Attributes