Cache Data Dependency on Oracle Database
Note
This feature is only available in NCache Enterprise Edition.
NCache provides OracleCacheDependency for notification-based dependencies with Oracle. Internally, NCache uses OracleDependency
to register data change notifications with the Oracle database server. Hence you need to understand the limitations and working mechanisms of OracleDependency
, while using this dependency. See the following Oracle Documentation for further details.
NCache provides an Oracle Dependency to synchronize the cache with the Oracle database. Cache items expire if a command results in a change in the database. Oracle Dependency is available for Oracle database 11g or later. Also, install Oracle Data Providers for .NET (version 10.1.0.2.0+).
The database change notifications are object-based, firing change notifications upon any object row modification. Therefore, check ROWID to confirm if the altered row is the one for which the event was registered. ROWIDs cannot be retrieved unless explicitly included in the query. So, the user has to specifically include ROWID in the query that is being registered with OracleDependency
, otherwise, the change notification will be fired if any row is modified in the table.
When ROWID is included in a query such as: SELECT ROWID, UnitPrice FROM Products WHERE ProductID = {product.ProductID}
- NCache will save the ROWIDs of rows for which the change notification is registered. When it receives any change notification, NCache will compare the ROWIDs to determine whether the row changed is the one for which the ROWID is registered. Otherwise, NCache will have no way to check against this, and items with a change notification registered are removed if any row in the table changes.
Prerequisites
Adding Data with Oracle Dependency
Altering data after addition with Oracle Dependency will remove it from the cache. OracleCacheDependency
is used to specify the dependency criteria, and then the item is added to the cache using the Add
or Insert
method.
The following example adds data with OracleCacheDependency
using the Insert
method. The Insert
method adds a new item with dependency, and if this data already exists in the cache, it overwrites its properties.
try
{
// Creating connection string to get connected with database.
string connectionString = "your_connection_string_here";
// Getting products from database.
List<Product> products = FetchProductFromDB();
foreach (Product product in products)
{
string productKey = $"Product: {product.ProductID}";
// Creating an Oracle dependency on the UnitPrice of product. Whenever the UnitPrice changes, the product is removed from the cache.
string query = $"SELECT ROWID, UnitPrice FROM Products WHERE ProductID = {product.ProductID}";
// Creating dependency on fetched products.
OracleCacheDependency dependency = new OracleCacheDependency(connectionString, query);
CacheItem productItem = new CacheItem(product);
// Adding Dependency to product item
productItem.Dependency = dependency;
// Adding CacheItem in cache
cache.Add(productKey, productItem);
}
}
catch (OperationFailedException ex)
{
// Exception can occur due to:
// Connection Failures
// Operation Timeout
// Operation performed during state transfer
}
catch (Exception ex)
{
// Any generic exception like ArgumentNullException or ArgumentException
// Exception may occur due to incorrect query format or invalid connection string
}
try
{
// Creating a connection string to establish connection with the database
String connString = "";
Connection connection = DriverManager.getConnection(connString);
// Create query which selects data on which cache data is dependent
String query = "SELECT ROWID, productName FROM Products WHERE productID = ?";
QueryCommand queryCommand = new QueryCommand(query);
queryCommand.getParameters().put("ProductID", productId);
// Get product from database against productId
Product product = fetchProductFromDb(productID);
// Create unique cache key for this product
String key = "Product:" + product.productID;
// Create oracle dependency
OracleCacheDependency oracleCacheDependency = new OracleCacheDependency(String.valueof(connection), query);
// Create new cache item and add oracle dependency to it
CacheItem cacheItem = new CacheItem(product);
cacheItem.setDependency(oracleCacheDependency);
// Add cache item in the cache item with oracle dependency
cache.insert(key, cacheItem);
// For successful addition of item with Oracle Dependency
// Update the record in the database and check if key is present
}
catch (OperationFailedException ex)
{
// Exception can occur due to:
// Connection Failures
// Operation Timeout
// Operation performed during state transfer
}
catch (Exception ex)
{
// Any generic exception like IllegalArgumentException or NullPointerException
}
try {
// Creating a connection string to establish connection with the database
val connString = "YourConnString"
val productID = "1001"
// Create query which selects data on which cache data is dependent
val query = "SELECT ROWID, productName FROM Products WHERE productID = ?"
val queryCommand = new QueryCommand(query)
queryCommand.setParameters(Map("ProductID" -> productID))
// Get product from database against productId
val product = fetchProductFromDb(productID)
// Create unique cache key for this product
val key = "Product:" + product.getProductId
// Create oracle dependency
val oracleCacheDependency = OracleCacheDependency(connString, query)
// Create new cache item and add oracle dependency to it
val cacheItem = new CacheItem(product)
cacheItem.setDependency(oracleCacheDependency)
// Add cache item in the cache item with oracle dependency
cache.insert(key, cacheItem)
// For successful addition of item with Oracle Dependency
// Update the record in the database and check if key is present
}
catch {
case exception: Exception => {
// Handle any errors
}
}
try
{
// Creating a connection string to establish connection with the database
var connection = new ActiveXObject("adodb.connection");
let connString = "...";
connection.Open(connString);
var result = new ActiveXObject("ADODB.Recordset");
let query = "Select ROWID, ProductId, ProductName, UnitPrice FROM dbo.Products WHERE ProductId = ?";
let queryCommand = new QueryCommand(query);
queryCommand.getParameters().put("CustomerID", this.customerId);
result.Open(query, connection);
// Get product from database against productId
let product = this.fetchProductFromDb(this.productId);
// Create unique cache key for this product
let key = "Product:" + product.ProductID;
// Create oracle dependency
var oracleCacheDependency = new ncache.OracleCacheDependency(connString, query);
// Create new cache item and add oracle dependency to it
let cacheItem = new ncache.CacheItem(product);
cacheItem.setDependency(oracleCacheDependency);
// Add cache item in the cache item with oracle dependency
this.cache.insert(key, cacheItem);
result.close();
connection.close();
// For successful addition of item with Oracle Dependency
// Update the record in the database and check if key is present
}
catch (error)
{
// Handle any errors
}
try:
# Creating a connection string to establish connection with the database
conn_string = "your_connection_string"
query = "SELECT ROWID, ProductId, ProductName, UnitPrice FROM dbo.Products WHERE ProductId = ?"
query_command = ncache.QueryCommand(query)
query_command.set_parameters({"CustomerID": "ALFKI"})
# Get product from database against productId
product = fetch_product_from_db("1001")
# Create unique cache key for this product
key = "Product:" + product.get_product_id()
# Create oracle dependency
oracle_cache_dependency = ncache.OracleCacheDependency(conn_string, query)
# Create new cache item and add oracle dependency to it
cache_item = ncache.CacheItem(product)
cache_item.set_dependency(oracle_cache_dependency)
# Add cache item in the cache item with oracle dependency
cache.insert(key, cache_item)
# For successful addition of item with Oracle Dependency
# Update the record in the database and check if key is present
except Exception as exp:
# Handle errors
Note
To ensure the operation is fail safe, it is recommended to handle any potential exceptions within your application, as explained in Handling Failures.
Add Data with Oracle Dependency using Stored Procedure
NCache lets you provide an Oracle Dependency on an item using a stored procedure. You can also specify the parameters to be passed along with the stored procedure, using the OracleCacheDependency
method.
The following example adds items to the cache with Oracle Dependency through the stored procedure using the Insert
method. The Insert
method adds a new item with dependency, and if this data already exists in the cache, it overwrites its properties.
// Creating connection string to get connected with database.
string connectionString = "your_connection_string_here";
string spGetUnitPriceByProductID = "sp_GetUnitPriceByProductID";
// Getting products from database.
List<Product> products = FetchProductFromDB();
foreach (Product product in products)
{
string productKey = $"Product: {product.ProductID}";
// Creating Param to be passed in stored procedure dictionary.
OracleCmdParams paramProductID = new OracleCmdParams
{
Type = OracleCmdParamsType.Int32,
Value = product.ProductID
};
// Creating stored procedure params.
Dictionary<string, OracleCmdParams> parameters = new Dictionary<string, OracleCmdParams>();
parameters.Add("@ProductID", paramProductID);
CacheItem productItem = new CacheItem(product);
// Creating an Oracle dependency on the UnitPrice of product. Whenever the UnitPrice changes, the product is removed from the cache.
OracleCacheDependency dependency = new OracleCacheDependency(connectionString, spGetUnitPriceByProductID, OracleCommandType.StoredProcedure, parameters);
// Adding Dependency to product item
productItem.Dependency = dependency;
// Adding CacheItem in cache
cache.Add(productKey, productItem);
}
// Create connection with the database
String connString = "your_connection_string_here";
Connection connection = DriverManager.getConnection(connString);
// Name of the stored procedure the item is dependent on
String storedProcedureName = "GetProductByID";
// Specify the Product ID passed as parameters
Map<String, OracleCmdParams> oracleCmdParamsMap = new HashMap<>();
oracleCmdParamsMap.put("ProductID", productId);
// Create oracle dependency with stored procedure
OracleCacheDependency oracleCacheDependency = new OracleCacheDependency(connString, storedProcedureName, OracleCommandType.StoredProcedure, oracleCmdParamsMap);
// Get product from database against productId
Product product = fetchProductFromDb(productId);
// Generate a unique cache key for this product
String key = "Product:" + product.productId;
// Create a new cache item and add oracle dependency to it
CacheItem cacheItem = new CacheItem(product);
cacheItem.setDependency(oracleCacheDependency);
// Add cache item in the cache with oracle dependency
cache.insert(key, cacheItem);
// For successful addition of item with Oracle Dependency
// Update the record in the database and check if key is present
// Create connection with the database
val connString = "YourConnectionString"
val productId = "1001"
// Name of the stored procedure the item is dependent on
val storedProcedureName = "GetProductByID"
// Specify the Product ID passed as parameters
val param = OracleCmdParams()
param.setValue(productId)
val oracleCmdParamsMap: Map[String, OracleCmdParams] = Map("ProductID" -> param)
// Create oracle dependency with stored procedure
val oracleCacheDependency = OracleCacheDependency(
connString,
storedProcedureName,
OracleCommandType.StoredProcedure,
oracleCmdParamsMap
)
// Get product from database against productId
val product = fetchProductFromDb(productId)
// Generate a unique cache key for this product
val key = "Product:" + product.getProductId
// Create a new cache item and add oracle dependency to it
val cacheItem = CacheItem(product)
cacheItem.setDependency(oracleCacheDependency)
// Add cache item in the cache with oracle dependency
cache.insert(key, cacheItem)
// For successful addition of item with Oracle Dependency
// Update the record in the database and check if key is present
// This is an async method
// Create connection with the database
var connection = new ActiveXObject("adodb.connection");
let connString = "your_connection_string_here";
connection.Open(connString);
// Name of the stored procedure the item is dependent on
let storedProcedureName = "GetProductByID";
// Specify the Product ID passed as parameters
let oracleCmdParamsMap = new Map();
oracleCmdParamsMap.set("ProductID", this.productId);
// Create oracle dependency with stored procedure
var oracleCacheDependency = new ncache.OracleCacheDependency(connString, storedProcedureName, OracleCommandType.StoredProcedure, oracleCmdParamsMap);
// Get product from database against productId
let product = this.fetchProductFromDb(this.productId);
// Generate a unique cache key for this product
let key = "Product:" + product.ProductID;
// Create a new cache item and add oracle dependency to it
let cacheItem = new ncache.CacheItem(product);
cacheItem.setDependency(oracleCacheDependency);
// Add cache item in the cache with oracle dependency
await this.cache.insert(key, cacheItem);
// For successful addition of item with Oracle Dependency
// Update the record in the database and check if key is present
connection.close();
# Create a connection string to connect with the database
conn_string = "your_connection_string_here"
# Name of the stored procedure the item is dependent upon
stored_procedure_name = "GetProductByID"
# Specify the Product ID passed as parameters
oracle_cmd_params = {"ProductID": "ALFKI"}
# Create oracle dependency with stored procedure
oracle_cache_dependency = ncache.OracleCacheDependency(conn_string, stored_procedure_name, ncache.OracleCommandType.STORED_PROCEDURE, oracle_cmd_params)
# Get product from database against productId
product = fetch_product_from_db("ALFKI")
# Generate a unique cache key for this product
key = "Product:" + product.get_product_id()
# Create a new cache item and add oracle dependency to it
cache_item = ncache.CacheItem(product)
cache_item.set_dependency(oracle_cache_dependency)
# Add cache item in the cache with oracle dependency
cache.insert(key, cache_item)
# For successful addition of item with Oracle Dependency
# Update the record in the database and check if key is present
Additional Resources
NCache provides sample application for Oracle dependency on GitHub.
See Also
Sync Cache with SQL Server
Cache Data Dependency on OleDB
CLR Procedures in SQL Server with Cache
Locking Data For Concurrency Control
Cache Data Dependency on External Source