• Products
  • Solutions
  • Customers
  • Resources
  • Company
  • Pricing
  • Download
Try Playground
  • Client Side API Programming
  • Continuous Query
  • Use Continuous Query
Show / Hide Table of Contents
  • Programmer's Guide
  • Setting Up Development Environment
    • .NET
      • Client API Prerequisites
      • Server-side API Prerequisites
    • Java
      • Client API Prerequisites
      • Server-side API Prerequisites
    • Python
      • Client API Prerequisites
    • Node.js
      • Client API Prerequisites
  • Client Side API Programming
    • Error Handling
    • Troubleshooting
    • Cache Keys and Data
    • How to Connect to Cache
    • Basic Operations - An Overview
      • Add Data
      • Update/Insert Data
      • Retrieve Data
      • Remove Data
    • Groups
      • Overview
      • Add/Update Data with Groups
      • Retrieve Data with Groups
      • Remove Data with Group
      • Search Group Data Using SQL
      • Delete Group Data Using SQL
    • Tags
      • Overview
      • Add/Update Data with Tags
      • Retrieve Data with Tags
      • Remove Data with Tags
      • Search Tag Data Using SQL
      • Delete Tag Data Using SQL
    • Named Tags
      • Overview
      • Add/Update Data with Named Tags
      • Remove Data with Named Tags
      • Search Data with Named Tags Using SQL
      • Delete Data with Named Tags Using SQL
    • Expirations
      • Overview
      • Absolute Expiration
      • Sliding Expiration
    • Data Dependency
      • Key Dependency
      • Multi-Cache Dependency
    • Dependency on Database
      • SQL Server
      • Oracle
      • OleDB with Polling
      • CLR Procedures in SQL Server
    • Dependency on External Source
      • File Dependency
      • Custom Dependency
      • Aggregate Dependency
    • Locks
      • Types of Locking
      • Pessimistic Locking
      • Optimistic Locking
    • SQL Query
      • Overview
      • Define Indexes Programmatically
      • Query with ExecuteReader and ExecuteScalar
      • Delete Data with ExecuteNonQuery
      • SQL Reference
    • LINQ Query
      • Overview
      • LINQ Query for Objects
      • LINQ Reference
    • Data Structures
      • Overview
      • List
      • Queue
      • Set
      • Dictionary
      • Counter
      • Invalidation Attributes
      • Searchable Attributes
      • Query on Data Structures
      • Remove from Data Structure
    • Events
      • Cache Level Events
      • Item Level Events
      • Management Level Events
    • Pub/Sub Messaging
      • Overview
      • Topics
      • Publish Messages
      • Subscribe to a Topic
      • Pub/Sub Events
    • Continuous Query
      • Overview
      • Use Continuous Query
    • Stream Processing
      • Add/Update Stream Data
      • Retrieve Stream Data
    • JSON
      • Overview
      • Use JSON Objects
      • Query JSON Data
    • Security API
      • Login with Credentials
    • Management API
    • Clear Cache
    • Error Logging
    • Location Affinity
  • Server-side API Programming
    • Loader and Refresher
      • Overview
      • Implement Loader and Refresher
      • Components of Loader/Refresher
    • Data Source Providers
      • Read-through
        • Implement Read-through
        • Use Read-through
      • Write-through
        • Implement Write-through
        • Use Write-through
        • Use Write-behind
    • Custom Dependency
      • Implement Extensible Dependency
      • Implement Bulk Extensible Dependency
      • Implement Notify Extensible Dependency
    • Bridge Conflict Resolver
    • Entry Processor
      • Overview
      • Implement Entry Processor
    • MapReduce
      • Overview
      • Implement MapReduce
      • Use MapReduce
    • MapReduce Aggregator
      • Overview
      • Implement and Use Aggregator
    • Compact Serialization
  • Client Side Features
    • ASP.NET Core Caching
      • Session Storage
        • Session Provider
        • IDistributedCache
        • Sessions Usage
        • Multi-site Session Provider
        • Session Sharing with ASP.NET
      • SignalR
        • NCache Extension for SignalR Core
      • Response Caching
        • Configure and Use
        • Configure with IDistributedCache
      • Data Caching
        • NCache API
        • IDistributedCache API
      • Data Protection Provider
        • Configure
    • Java Web App Caching
      • Web Sessions
        • Overview
        • Configure App
          • Add Maven Dependencies
          • Deploy Application
        • Multi-site Sessions
    • Node.js App Caching
      • Web Sessions
    • ASP.NET Caching Benefits and Overview
      • ASP.NET Session State Provider Properties
      • Multi-region ASP.NET Session State Provider Configuration
      • Session Sharing between ASP.NET and ASP.NET Core
      • ASP.NET SignalR Backplane
        • NCache Extension for SignalR
      • ASP.NET View State Caching
        • View State Content Optimization Configuration
        • Group View State with Sessions
        • Limit View State Caching
        • Page Level Grouping
      • ASP.NET Output Cache
        • Output Caching Provider Overview
        • Output Cache with Custom Hooks
  • .NET Third Party Integrations
    • Entity Framework (EF) Core
      • Installation
      • Configure
      • EF Core Extension Methods
        • Extension Methods
        • Cache Handle
        • Caching Options
        • Query Deferred API
      • Logging in EF Core
    • Entity Framework EF 6
      • EF Second Level Cache
      • EF Caching Resync Provider
      • EF Caching Configuration File
    • NHibernate
      • Second Level Cache
      • Query Caching
      • Synchronize Database with Cache
    • Debug NCache Providers in Visual Studio
  • Java Third Party Integrations
    • Hibernate
      • Second Level Cache
      • Configure Cacheable Objects and Regions
      • Configure Application
      • Query Caching
    • Spring
      • Overview
      • Use NCache with Spring
        • Configure Generic Provider
        • Configure JCache Spring Caching Provider
        • Configure Caching Declaration
        • Configure Spring Sessions
    • JCache API
      • CRUD Operations
      • Expiration
      • Events
  • Third-Party Wrappers
    • AppFabric to NCache Migration
      • AppFabric API vs. NCache API
      • Configuration Differences Between AppFabric and NCache
      • Migrating from an AppFabric Application to NCache
    • Redis to NCache Migration
      • Redis to NCache Migration
    • Memcached Wrapper
      • Memcached Gateway Approach
      • Memcached Client Plugin for .NET

Using Continuous Query [Deprecated]

Assuming that you have indexed the required searchable attributes, you are now required to implement the 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.

Prerequisites

  • .NET
  • Java
  • Python
  • Node.js
  • Legacy API
  • To learn about the standard prerequisites required to work with all NCache client-side features, please refer to the given page on Client-Side API Prerequisites.
  • Indexing for searchable objects and their attributes need to be configured first as explained in Configuring Query Indexes in Administrator's Guide.
  • Cache should have some data related to configured attributes.
  • For API details, refer to: ICache, EventDataFilter, EventType, ExecuteReader, RegisterCQ, UnRegisterCQ, UnRegisterNotification, ContinuousQuery, RegisterNotification, QueryDataNotificationCallback, ICacheReader, FieldCount, Read, Insert, CQEventArg, GetValue.
  • To learn about the standard prerequisites required to work with all NCache client-side features, please refer to the given page on Client-Side API Prerequisites.
  • Indexing for searchable objects and their attributes need to be configured first as explained in Configuring Query Indexes in Administrator's Guide.
  • Cache should have some data related to configured attributes.
  • For API details, refer to: Cache, EventDataFilter, EventType, executeReader, registerCQ, unRegisterCQ, removeDataModificationListener, CacheItem, CacheItemVersion, insert, CQEventArg, getEventType, read, getValue, ContinuousQuery, addDataModificationListener, getFieldCount, CacheReader.
  • To learn about the standard prerequisites required to work with all NCache client-side features, please refer to the given page on Client-Side API Prerequisites.
  • Indexing for searchable objects and their attributes need to be configured first as explained in Configuring Query Indexes in Administrator's Guide.
  • Cache should have some data related to configured attributes.
  • For API details, refer to: get_event_type, execute_reader, register_cq, un_register_cq, remove_data_modification_listener, CacheItem, insert, get_field_count, add_data_modification_listener, ContinuousQuery, read, get_value, EventType, CQEventArg.
  • To learn about the standard prerequisites required to work with all NCache client-side features, please refer to the given page on Client-Side API Prerequisites.
  • Indexing for searchable objects and their attributes need to be configured first as explained in Configuring Query Indexes in Administrator's Guide.
  • Cache should have some data related to configured attributes.
  • For API details, refer to: Cache, EventDataFilter, EventType, executeReader, registerCQ, unRegisterCQ, removeDataModificationListener, CacheItem, insert, getEventType, getValue, read, getFieldCount, ContinuousQuery, addDataModificationListener.
  • Create a new Console Application.
  • Make sure that the data being added is serializable.
  • Add NCache References by locating %NCHOME%\NCache\bin\assembly\4.0 and adding Alachisoft.NCache.Web and Alachisoft.NCache.Runtime as appropriate.
  • Include the Alachisoft.NCache.Runtime.Events and Alachisoft.NCache.Web.Caching namespace in your application.

Step 1: Register Query and Notifications

  1. First you need to 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.

  2. Once Continuous Query has been created, the pre-defined callbacks are registered with the query. The callbacks are registered according to EventType and EventDataFilter.

  3. The Continuous Query can now be registered on the server using RegisterCQ. You can use this method multiple times in your application to receive notifications for a change in the dataset of your query.

  4. Any modifications in cache event notifications will be triggered according to the event type. For querying cached data, the ExecuteReader executes the query and the result set generated is then read on the client-side, chunk by chunk.

  5. 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 it is added to the query result set, thereby firing an ItemAdded event.

Warning

If the connection breaks between a server and a client, any events fired within this duration will not be received by the client.

  • .NET
  • Java
  • Python
  • Node.js
  • Legacy API
// Query for required operation
string query = "SELECT $VALUE$ FROM Alachisoft.NCache.Samples.Data.Product WHERE Category = ?";

// Create query command and add parameters
var queryCommand = new QueryCommand(query);
queryCommand.Parameters.Add("Category", "Beverages");

// Create Continuous Query
var cQuery = new ContinuousQuery(queryCommand);

// Item add, update, remove notification
// EventDataFilter.DataWithMetadata returns the keys with the data and meta added with data
cQuery.RegisterNotification(OnChangeInQueryResultSet, EventType.ItemAdded | EventType.ItemUpdated | EventType.ItemRemoved, EventDataFilter.DataWithMetadata);

// Register continuousQuery on server
cache.MessagingService.RegisterCQ(cQuery);
// Query for the desired operation
String query = "SELECT $VALUE$ FROM CQ.Product WHERE productId = ?";

// Create query command
QueryCommand queryCommand = new QueryCommand(query);
// Set parameters
HashMap<String, Object> parameters = queryCommand.getParameters();
parameters.put("productId", "Beverages");

// Create Continuous Query
ContinuousQuery cQuery = new ContinuousQuery(queryCommand);

// Register notifications for continuous query (ItemAdded, ItemUpdated, and ItemRemoved events)
    cQuery.addDataModificationListener(new QueryDataModificationListener() {
        @Override
        public void onQueryDataModified(String key, CQEventArg arg) {
            // Your callback method to handle the notifications
            // For instance, you can call the 'onChangeInQueryResultSet' method from your earlier code here
            onChangeInQueryResultSet(key, arg);
        }
    }, EnumSet.of(EventType.ItemAdded, EventType.ItemUpdated, EventType.ItemRemoved), EventDataFilter.DataWithMetadata);

// Register the continuous query on the server
cache.getMessagingService().registerCQ(cQuery);
System.out.println("Registered Successfully");

# Query for required operation
query = "SELECT $Value$ FROM FQN.Product WHERE category = ?"

query_command = ncache.QueryCommand(query)
query_command.set_parameters({"Category": "Beverages"})

# Create continuous query
continuous_query = ncache.ContinuousQuery(query_command)

event_type = [ncache.EventType.ITEM_REMOVED]

# Item remove notification
# EventDataFilter.Metadata returns cache keys + item metadata on updation
continuous_query.add_data_modification_listener(cq_event_listener, event_type, ncache.EventDataFilter.NONE)

# Register continuous query on server
cache.get_messaging_service().register_cq(continuous_query)

reader = cache.get_search_service().execute_reader(query_command)

if reader.get_field_count() > 0:
    while reader.read():
        result = reader.get_value(Product, 1)
        # Perform operations
else:
    # None query result set returned
    print("Query result is None")

# Update Product data in cache to trigger callback
updated_product = Product()
updated_product.set_product_id(1001)
updated_product.set_product_name("Tea")

key = "Product:" + updated_product.get_product_id()

cache_item = ncache.CacheItem(updated_product)

# Trigger add notifications
version = cache.insert(key, cache_item)
# This will add item to the result set as it matches query criteria
// Query for required operation
let query = "SELECT Values FROM FQN.Product WHERE Category = ?";

var queryCommand = new QueryCommand(query);
queryCommand.getParameters().put("Category", "Beverages");
​
// Create continuous query
let continuousQuery = new ncache.ContinuousQuery(queryCommand);
​
let listener = new ncache.EventFilter();
var eventType = ncache.EnumSet.of(ncache.EventType.ItemAdded, ncache.EventType.ItemRemoved, ncache.EventType.ItemUpdated);
​
// Item remove notification
// EventDataFilter.Metadata returns cache keys + item metadata on updation
continuousQuery.addDataModificationListener(listener, eventType, ncache.EventDataFilter.None);
​
// Register continuous query on server
await this.cache.getMessagingService().registerCQ(continuousQuery);
​
let reader = await this.cache.getSearchService().executeReader(queryCommand);
​
if (reader.getFieldCount() > 0)
{
    while (reader.read())
    {
        let result = reader.getValue(1, Product);
        // Perform operations
    }
}
else
{
    // Null query result set returned
}
​
// Update Product data in cache to trigger callback
let updatedProduct = new Product();
updatedProduct.setProductID(1001);
updatedProduct.setProductName("Tea");

let key = "Product:" + updatedProduct.getProductID();

let cacheItem = new ncache.CacheItem(updatedProduct);
​
// Trigger add notifications
let version = await this.cache.insert(key, cacheItem);
// This will add item to the result set as it matches query criteria
public class CQ
{
    static void Main(string[] args)
    {
        Cache cache = NCache.InitializeCache("mycache");

        string queryString = "Select Product WHERE this.supplier=?";

        Hashtable values = new Hashtable();
        values.Add("supplier", "Carlos Diaz");

        ContinuousQuery continuousQuery = new ContinuousQuery(queryString, values);

        // Register notifications for query events
        continuousQuery.RegisterNotification(new QueryDataNotificationCallback(ItemAddedCallBack), EventType.ItemAdded, EventDataFilter.None);
        continuousQuery.RegisterNotification(new QueryDataNotificationCallback(QueryItemCallBack), EventType.ItemUpdated | EventType.ItemRemoved, EventDataFilter.None);

        // Register cache clear notification
        continuousQuery.RegisterClearNotification(new ContinuousQueryClearCallback(CacheClear));

        // Register Continuous Query on server
        cache.RegisterCQ(continuousQuery);
    }
}

Step 2: Register Callback for Events

Assuming that you have indexed the required searchable attributes, you can implement the 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. A callback can be registered for multiple events as shown below.

  • .NET
  • Java
  • Python
  • Node.js
  • Legacy API
public void OnChangeInQueryResultSet(string key, CQEventArg arg)
{
    switch (arg.EventType)
    {
        case EventType.ItemAdded:
            Console.WriteLine($"Item with key '{key}' has been added to result set of continuous query");
            break;

        case EventType.ItemUpdated:
            Console.WriteLine($"Item with key '{key}' has been updated in the result set of continuous query");

            // Get updated Product object
            // Item can be used if EventDataFilter is DataWithMetadata or Metadata
            if (arg.Item != null)
            {
                Product updatedProduct = arg.Item.GetValue<Product>();
                Console.WriteLine($"Updated product '{updatedProduct.ProductName}' with key '{key}' has ID '{updatedProduct.ProductID}'");
            }
            break;

        case EventType.ItemRemoved:
            Console.WriteLine($"Item with key '{key}' has been removed from result set of continuous query");
            break;
    }
}
public static void onChangeInQueryResultSet(String key, CQEventArg arg) {
    switch (arg.getEventType()) {
        case ItemAdded:
            System.out.println("Item with key '" + key + "' has been added to result set of continuous query");
            break;

        case ItemUpdated:
            System.out.println("Item with key '" + key + "' has been updated in the result set of continuous query");
            // Get updated Product object
            // Item can be used if EventDataFilter is DataWithMetadata or Metadata
            if (arg.getItem() != null) {
                Product updatedProduct = (Product) arg.getItem().getValue(Product.class);
                System.out.println("Updated product '" + updatedProduct.getProductName() + "' with key '" + key + "' has ID '" + updatedProduct.getProductID() + "'");
            }
            break;

        case ItemRemoved:
            System.out.println("Item with key '" + key + "' has been removed from result set of the continuous query");
            break;
        }
    }
# Precondition: Cache is already connected
def query_item_callback(key: str, arg: ncache.CQEventArg):
    if arg.get_event_type() is ncache.EventType.ITEM_ADDED:
        # Key has been added to the cache
        print(key + " added to cache")
    if arg.get_event_type() is ncache.EventType.ITEM_UPDATED:
        # Key has been updated in the cache
        # Get updated product object
        if arg.get_item() is not None:
            updated_product = arg.get_item().get_value(Product)
            # Perform operations accordingly
    if arg.get_event_type() is ncache.EventType.ITEM_REMOVED:
        # key has been removed from the cache
        print(key + " removed from cache")
// This is an async method
queryItemCallback(key, arg)
{
    switch (arg.getEventType())
    {
        case ncache.ItemAdded:
            // Key has been added to the cache
        break;
        case ncache.ItemUpdated:
            // Key has been updated in the cache
            // Get updated product object

            if (arg.getItem() != null)
            {
                let updatedProduct = arg.getItem().getValue(Product);
                // Perform operations accordingly
            }
        break;
        case ncache.ItemRemoved:
            // key has been removed from the cache
        break;
    }
}
static void ItemAddedCallBack(string key, CQEventArg arg)
{
    EventCacheItem item = arg.Item; // Perform operations when item is added
}

static void QueryItemCallBack(string key, CQEventArg arg)
{
    switch (arg.EventType)
    {
        case EventType.ItemRemoved:
            // Perform operations when item is removed
            break;
        case EventType.ItemUpdated:
            // Perform operations when item is updated
            break;
    }
}

// Create target methods
static void CacheClear()
{
    Cache cache = null;
    cache.Clear();
}
Note

To ensure the operation is fail-safe, it is recommended to handle any potential exceptions within your application, as explained in Handling Failures.

Step 3: Unregister Notifications from Continuous Query

Notifications can be unregistered from Continuous Query when they are no longer required in the application. You can unregister notifications for a specific event type if multiple event types have been registered using the UnRegisterNotification method. For example, if ItemAdded and ItemRemoved event types were registered but your business logic no longer requires events for ItemAdded, you can specifically unregister notifications for ItemAdded events, while still keeping the add and remove notifications registered.

When a client unregisters a notification from a Continuous Query, it only impacts that specific client. Other clients with the same notifications remain unaffected, allowing independent management of subscriptions. However, this method cannot unregister all CQ notifications through this method. For that, a separate method UnRegisterCQ is used. In the following example, an event notification for an item added notification is unregistered from a Continuous Query.

  • .NET
  • Java
  • Python
  • Node.js
// Unregister notifications for ItemAdded events from continuous query
cQuery.UnRegisterNotification((OnChangeInQueryResultSet), EventType.ItemAdded);
// Unregister notifications for ItemAdded events only

cQuery.removeDataModificationListener(new QueryDataModificationListener() {
@Override
public void onQueryDataModified(String key, CQEventArg arg) {
    // Your callback method to handle the notifications
    // For instance, you can call the 'onChangeInQueryResultSet' method from your earlier code here
    onChangeInQueryResultSet(key, arg);
}
}, EnumSet.of(EventType.ItemAdded, EventType.ItemUpdated, EventType.ItemRemoved));
# Unregister notifications for ItemAdded events only
event_type = [ncache.EventType.ITEM_ADDED]
c_query.remove_data_modification_listener(cq_event_listener, event_type)
// Unregister notifications for ItemAdded events only
var eventType = ncache.EnumSet.of(ncache.EventType.ADDED);
continuousQuery.removeDataModificationListener(listener, eventType);

Step 4: Unregister Continuous Query from Server

Once the application is no longer interested in receiving notifications for changes in a query result set, the registered Continuous Query should be unregistered from the server using the UnRegisterCQ method. Using this method, the result set isn’t immediately removed from the server. If it is the last client, the result set will be removed from the cache. Otherwise, the result set remains in the cache, but that specific client will stop receiving notifications for it. Essentially, it depends on the number of clients registered for that result set.

The UnregisterCQ method takes a ContinuousQuery object as an argument to unregister the callbacks that are no longer fired after this call. The following code example demonstrates how to unregister a Continuous Query from the cache server.

  • .NET
  • Java
  • Python
  • Node.js
// Unregister Continuous Query from server
cache.MessagingService.UnRegisterCQ(cQuery);
// Unregister cq from server
cache.getMessagingService().unRegisterCQ(cQuery);
# Unregister cq from server
cache.get_messaging_service().un_register_cq(c_query)
// Unregister cq from server
await this.cache.getMessagingService().unRegisterCQ(continuousQuery);

Additional Resources

NCache provides a sample application for Continuous Queries on GitHub.

See Also

.NET: Alachisoft.NCache.Runtime.Events namespace.
Java: com.alachisoft.ncache.events namespace.
Python: ncache.runtime.caching.events class.
Node.js: ContinuousQuery class.

In This Article
  • Prerequisites
  • Step 1: Register Query and Notifications
  • Step 2: Register Callback for Events
  • Step 3: Unregister Notifications from Continuous Query
  • Step 4: Unregister Continuous Query from Server
  • Additional Resources
  • See Also

Contact Us

PHONE

+1 (214) 764-6933   (US)

+44 20 7993 8327   (UK)

 
EMAIL

sales@alachisoft.com

support@alachisoft.com

NCache
  • NCache Enterprise
  • NCache Professional
  • Edition Comparison
  • NCache Architecture
  • Benchmarks
Download
Pricing
Try Playground

Deployments
  • Cloud (SaaS & Software)
  • On-Premises
  • Kubernetes
  • Docker
Technical Use Cases
  • ASP.NET Sessions
  • ASP.NET Core Sessions
  • Pub/Sub Messaging
  • Real-Time ASP.NET SignalR
  • Internet of Things (IoT)
  • NoSQL Database
  • Stream Processing
  • Microservices
Resources
  • Magazine Articles
  • Third-Party Articles
  • Articles
  • Videos
  • Whitepapers
  • Shows
  • Talks
  • Blogs
  • Docs
Customer Case Studies
  • Testimonials
  • Customers
Support
  • Schedule a Demo
  • Forum (Google Groups)
  • Tips
Company
  • Leadership
  • Partners
  • News
  • Events
  • Careers
Contact Us

  • EnglishChinese (Simplified)FrenchGermanItalianJapaneseKoreanPortugueseSpanish

  • Contact Us
  •  
  • Sitemap
  •  
  • Terms of Use
  •  
  • Privacy Policy
© Copyright Alachisoft 2002 - 2025. All rights reserved. NCache is a registered trademark of Diyatech Corp.
Back to top