List Behavior and Usage in Cache
Note
This feature is only available in NCache Enterprise Edition.
A list in NCache is an extension of the .NET IList, which also provides additional properties. A list is an unordered data type, where data can be added or removed from any point of the list.
For example, lists can be used to maintain a list of the products being added to cart for an e-commerce website. Let's suppose user1 adds the products Umbrella, Green Apples and Coffee to the cart. Before making the transaction, the product Green Apples is removed and a new product Pears is added. This is possible because a list can be updated from any point in the list.
NCache further enhances this list by providing NCache specific features such as expiration, dependency, groups and more to the list. In this scenario, the company wants the cart list to be maintained only as long as the session is active. Hence, expiration can be associated with each list created which is equal to the session timeout value.
Since NCache List is an extension of the .NET Framework IList, you can still use all methods exposed by IList along with NCache's methods which are cache-specific. This ensures familiarity and flexibility with the existing framework.
Behavior
- A list can be of any primitive type or custom object.
- A list of CacheItem and nested lists are not supported yet.
- Lists can be directly accessed by index.
- Lists are named; you need to provide a unique cache key for the list.
- Null is not a supported value type.
- Duplicate values are supported.
Pre-requisites
- Include the following namespaces in your application:
Alachisoft.NCache.Client.DataTypes
Alachisoft.NCache.Client.DataTypes.Collections
Alachisoft.NCache.Client
Alachisoft.NCache.Runtime.Exceptions
- The application must be connected to cache before performing the operation.
- Cache must be running.
- To ensure the operation is fail safe, it is recommended to handle any potential exceptions within your application, as explained in Handling Failures.
Create List and Add Data
The following code sample shows how a list of Product type can be created in cache using CreateList against the cache key "ProductList". Products are added to the list and then a new range of products is added to the list using Add and AddRange.
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
// Specify unique cache key for list
string key = "ProductList";
// Create list of Product type
IDistributedList<Product> list = cache.DataTypeManager.CreateList<Product>(key);
// Check if the list exists in cache
// using cache.Contains()
// Get products to add to list
Product[] products = FetchProducts();
foreach (var product in products)
{
// Add products to list
list.Add(product);
}
// Get new products
Product[] newProducts = FetchNewProducts();
// Append list of new Products to existing list
list.AddRange(newProducts);
// You can check count of items in list using
// list.Count
}
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.
Update Items in List
Since lists can be accessed via index, you can update lists and items in them using indexes. The following code sample updates a value in an existing list (created in previous example) using the index. It then gets a sale item and adds it to the first index of the list using InsertAtHead.
try
{
// Pre-condition: Cache is already connected
// "list" is created in previous example
// Update value of index with updated product
Product updatedProduct = GetUpdatedProductByID(11);
list[11] = updatedProduct;
// Get product on sale to insert at head of List
Product saleProduct = FetchSaleItem();
list.InsertAtHead(saleProduct);
}
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
// Item being added on an index out of range of list. Make sure index is
// lesser than the size of list, or
// a non-negative integer
}
Fetch List from Cache
You can fetch a list from cache using GetList, which takes a cache key as parameter. This key is the name of the list which is specified during list creation.
Warning
If the item being fetched is not of List type, a Type mismatch
exception is thrown.
try
{
// Pre-condition: Cache is already connected
// List with this key already exists in cache
string key = "ProductList";
// Get list and show items of list
IDistributedList<Product> retrievedList =
cache.DataTypeManager.GetList<Product>(key);
if (retrievedList != null)
{
foreach (var item in retrievedList)
{
// Perform operations
}
}
else
{
// List does not exist
}
}
catch (OperationFailedException ex)
{
// NCache specific exception
if (ex.ErrorCode == NCacheErrorCodes.NOT_A_LIST)
{
// Item being fetched is not of List type;
// Cache key corresponds to an item of different data type
}
else
{
// 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
}
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 List
Items can be removed from a list against a given range of items. The following code sample removes the range of items for the expired products using RemoveRange.
Tip
To remove the whole list from cache, refer to the Remove Data Structures From Cache page.
Note
If key specified to be removed does not exist, nothing is returned. You can verify number of keys returned using the return type of RemoveRange.
try
{
// Pre-condition: Cache is already connected
// List with this key already exists in cache
string key = "ProductList";
// Get list to remove items
IDistributedList<Product> retrievedList =
cache.DataTypeManager.GetList<Product>(key);
// Get range of expired products to be removed
List<Product> itemsToRemove = FetchExpiredProducts();
// Remove this range from retrievedList
// Number of keys removed is returned
int itemsRemoved = retrievedList.RemoveRange(itemsToRemove);
}
catch (OperationFailedException ex)
{
// NCache specific exception
if (ex.ErrorCode == NCacheErrorCodes.NOT_A_LIST)
{
// Item being fetched is not of List type;
// Cache key corresponds to an item of different data type
}
else
{
// 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
}
Recommendation: To ensure the operation is fail safe, it is recommended to handle any potential exceptions within your application, as explained in Handling Failures.
Event Notifications on Lists
You can register cache events as well as data type events on a data type such as list. 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 list in cache.
Once a list is created in cache, an ItemAdded
cache level event is fired. However, once an item is added to list, an ItemAdded
data type event is fired, and an ItemUpdated
cache level event is fired.
Register Event on List Created
try
{
// Pre-condition: Cache is connected
// Unique cache key for list
string key = "ProductList";
// Create list of Product type
IDistributedList<Product> list = cache.DataTypeManager.CreateList<Product>(key);
// Register ItemAdded, ItemUpdated, ItemRemoved events on list created
// DataTypeNotificationCallback is callback method specified
list.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 Lists
Lists can be explicitly locked and unlocked to ensure data consistency. The following code sample creates a list and locks it for a period of 10 seconds using Lock(), and then unlocks it using Unlock().
try
{
// Pre-conditions: Cache is already connected
// List exists with key "ProductList"
// Cache Key
string key = "ProductList";
// Get list
IDistributedList<Product> list = cache.DataTypeManager.GetList<Product>(key);
bool isLocked = list.Lock(TimeSpan.FromSeconds(10));
if (isLocked)
{
// List is successfully locked for 10 seconds
// Unless explicitly unlocked
}
else
{
// List is not locked because either:
// List is not present in the cache
// List is already locked
}
list.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 List datatype at:
- GitHub
- Shipped with NCache: %NCHOME%\samples\dotnet\DataTypes\DistributedList
See Also
List Behavior and Usage in Cache
Queue Behavior and Usage in Cache
Sets Behavior and Usage in Cache
Dictionary Behavior and Usage in Cache
Using Counter in Cache