Using Continuous Query
Assuming that you have indexed the required searchable attributes, you are now required to implement continuous query in your application. Keeping in mind the purpose of continuous queries, the first thing you need to do is to define all the callbacks that need to be executed once the result set of your query is in any way changed. Then, we need to register the continuous query with the cache server.
If all your applications don't require tracking of any query result set, then you should not only unregister notifications but also unregister the query from your cache.
Pre-Requisites
- Searchable attributes should be configured on cache using query indexes.
- Cache should have some data related to configured attributes.
- Include the following namespaces in your application:
Alachisoft.NCache.Web.Caching
Alachisoft.NCache.Runtime.Events
- To ensure the operation is fail safe, it is recommended to handle any potential exceptions within your application, as explained in Handling Failures.
Step 1: Register Callback for Events
Assuming that you have indexed the required searchable attributes, you can implement Continuous Query in your application. This requires you to define all the callbacks that need to be executed once the result set of your query is modified. Then, we need to register the Continuous Query with the cache server.
A callback can be registered for multiple events.
static void QueryItemCallBack(string key, CQEventArg arg)
{
switch (arg.EventType)
{
case EventType.ItemAdded:
// "key" has been added to cache
break;
case EventType.ItemUpdated:
// "key" has been updated in cache
// Get updated Product object
if (arg.Item != null)
{
Product updatedProduct = arg.Item.Value as Product;
// Perform operations
}
break;
case EventType.ItemRemoved:
// "key" has been removed from cache
break;
}
}
Step 2: Register Query and Notifications
After the callbacks are registered, create a Continuous Query, which specifies the criteria for the result set of which the events will be fired. This query will be registered against the server.
Once Continuous Query has been created, the pre-defined callbacks are registered with the query. The callbacks are registered according to EventType and EventDataFilter.
The continuous query can now be registered on the server using RegisterCQ(). You can use this method multiple times in your application to receive the notifications for a change in the dataset of your query.
Any modifications in cache event notifications will be triggered according to the event type. For querying cached data, ExecuteReaderCQ executes the query and registers the continuous query for callbacks in case of changes in data fulfilling the query’s criteria. The result set generated is then read at client side, chunk by chunk.
You can trigger events by modifying cache data such that it affects the result set. The code sample updates an existing cache item such that is added to the query result set, thereby firing an ItemAdded event.
Warning
If the connection breaks between a server and client, any events fired within this duration will not be received by the client.
Recommendation: To ensure the operation is fail safe, it is recommended to handle any potential exceptions within your application, as explained in Handling Failures.
try
{
// Pre-condition: Cache is already connected
// Create Continuous Query
string queryString = "Select Data.Product WHERE this.Category=?";
Hashtable values = new Hashtable();
values.Add("Category", "Beverages");
// Register continuous query on server
ContinuousQuery cQuery = new ContinuousQuery(queryString, values);
// Item add notification
// EventDataFilter.None returns the cache keys added
cQuery.RegisterNotification(new QueryDataNotificationCallback(QueryItemCallBack), EventType.ItemAdded, EventDataFilter.None);
// Item update notification
// EventDataFilter.DataWithMetadata returns cache keys + modifed item + metadata
cQuery.RegisterNotification(new QueryDataNotificationCallback(QueryItemCallBack), EventType.ItemUpdated, EventDataFilter.DataWithMetadata);
// Item Remove notification
// EventDataFilter.Metadata returns cache keys + item metadata on removal
cQuery.RegisterNotification(new QueryDataNotificationCallback(QueryItemCallBack), EventType.ItemRemoved, EventDataFilter.Metadata);
// Register continuousQuery on server
cache.RegisterCQ(cQuery);
// Query Cached Data
ICacheReader reader = cache.ExecuteReaderCQ(cQuery);
// If resultset is not empty
if (reader.FieldCount > 0)
{
while (reader.Read())
{
Product productRetrieved = reader[1] as Product;
// reader[0] = Cache key
// reader[1] = Product object
// Perform operations
}
}
else
{
// Null query result set returned
}
// Update Product Data in Cache to trigger ItemAdded
Product updatedProduct = new Product();
updatedProduct.ProductName = "Coffee";
updatedProduct.Category = "Beverages"; // Complies with criteria
string key = $"Product:(updatedProduct.ProductID)";
cache.Insert(key, updatedProduct);
// This will add the item to the result set
// as it matches query criteria
}
catch (OperationFailedException ex)
{
// NCache specific exceptions:
// Connection Failure
// Operation Timeout
}
catch (Exception ex)
{
// Any generic exception like ArgumentException, ArgumentNullException
}
Step 3: Unregister Notifications from Continuous Query
Notifications can be unregistered from Continuous Query when they are no more required in application. You can unregister notifications for a specific event type if multiple event types have been registered using UnRegisterNotification method.
For example, if ItemAdded
and ItemRemoved
event types were registered but your business logic no longer requires events for ItemAdded
, you specifically unregister notifications for ItemAdded
events.
// Unregister notifications for remove operation only
cQuery.UnRegisterNotification(new QueryDataNotificationCallback(QueryItemCallBack), EventType.ItemAdded);
Step 4: Unregister Continuous Query from Server
Once the application is no more interested in receiving notifications for changes in a query result set, the registered continuous query should be unregistered from server.
UnregisterCQ takes as argument an object of ContinuousQuery
to unregister the callbacks which are no more fired after this call.
// Unregister Continuous Query from server
cache.UnRegisterCQ(cQuery);
Shipped Sample Code
For a full functioning .NET application executing Continuous Query, you can use the samples shipped with NCache which are placed at:
- .NET Framework: %NCHOME%\samples\dotnet\ContinuousQuery
- .NET Core: %NCHOME%\samples\dotnetcore\ContinuousQuery
- Java: %NCHOME%\samples\java\ContinuousQuery
See Also
Search Cache with SQL
SQL Reference
Cache Events
Pub/Sub Messaging