Dapper API Usage with NCache
The NCache Dapper integration provides QueryCached<T> for executing queries with NCache cache-aside behavior. The application uses the same query call for both cache lookup and database fallback. NCache is checked first, and the database query executes only when the required cached result is unavailable or a refresh is explicitly requested.
Note
For general Dapper concepts and APIs, refer to the Dapper documentation.
Prerequisites
Before using Dapper with NCache, ensure that the following prerequisites are fulfilled:
- Install the following NuGet package in your application:
- OpenSource:
NCache.OSS.Dapper
- OpenSource:
- Include the following namespaces:
NCache.OSS.DapperAlachisoft.NCache.Client
- The NCache cache must already exist and must be running.
- Configure the NCache connection and
NCacheCacheProviderbefore usingQueryCached<T>. - Make sure query result objects being stored in NCache are serializable.
QueryCached API
QueryCached<T> provides the following signature:
IEnumerable<T> QueryCached<T>(
this IDbConnection cnn,
string sql,
object? param = null,
CacheOptions? options = null,
INCacheCacheProvider? cacheProvider = null,
string? customCacheKey = null)
CacheOptions Properties
CacheOptions controls NCache caching behavior for an individual QueryCached<T> call.
| Property | Description |
|---|---|
Expiration |
Specifies the expiration duration for the cached query result. It overrides DapperNCache.DefaultExpiration when set. |
IsSliding |
Specifies whether the configured expiration is sliding. The default is false. |
ForceUpdate |
Removes the existing cached result, executes the query against the database, and refreshes NCache. The default is false. |
ErrorEnabled |
Specifies whether cache operation failures are propagated to the application. The default is false, which causes cache operation failures to be swallowed. |
Important
Unless customCacheKey is provided, QueryCached<T> always generates the cache key internally using:
CacheKeyGenerator.GenerateCacheKey(
cnn.Database,
sql,
param,
typeof(T))
Cache a Query Result
Once the NCache provider is configured, use QueryCached<T> to execute a cached query:
var users = connection.QueryCached<User>(
"SELECT * FROM Users");
If the automatically generated cache key does not exist in NCache:
- The database query executes.
- The returned result is stored in NCache.
- The result is returned to the application.
If the cached result already exists, it is returned from NCache.
Cache a Parameterized Query
For a parameterized query:
var users = connection.QueryCached<User>(
"SELECT * FROM Users WHERE IsActive = @IsActive",
new
{
IsActive = true
});
No cache key needs to be supplied. QueryCached<T> automatically generates the key using:
CacheKeyGenerator.GenerateCacheKey(
cnn.Database,
sql,
param,
typeof(T))
The generated key accounts for the database, query, parameters, and result type.
Cache a Query with Absolute Expiration
Specify CacheOptions.Expiration to control how long the query result remains cached:
var users = connection.QueryCached<User>(
"SELECT * FROM Users WHERE IsActive = @IsActive",
new { IsActive = true },
new CacheOptions
{
Expiration = TimeSpan.FromMinutes(5),
IsSliding = false
});
NCacheCacheProvider applies the configured absolute expiration when storing the result in NCache.
Cache a Query with Sliding Expiration
Set IsSliding to true for sliding expiration:
var users = connection.QueryCached<User>(
"SELECT * FROM Users WHERE IsActive = @IsActive",
new { IsActive = true },
new CacheOptions
{
Expiration = TimeSpan.FromMinutes(5),
IsSliding = true
});
The expiration metadata is applied to the NCache CacheItem before it is inserted into the cache.
Use Default Expiration
Applications can configure default expiration at startup:
DapperNCache.DefaultExpiration =
TimeSpan.FromMinutes(30);
DapperNCache.DefaultIsSliding = false;
Queries that do not specify CacheOptions.Expiration use these defaults. However, per-query CacheOptions.Expiration takes precedence over DapperNCache.DefaultExpiration. If neither is configured, the cached result does not expire automatically.
Force a Cache Refresh
Use ForceUpdate to refresh a cached query result:
var users = connection.QueryCached<User>(
"SELECT * FROM Users",
options: new CacheOptions
{
ForceUpdate = true
});
When ForceUpdate is enabled:
- The existing cache entry is removed.
- The cached value is not returned.
- The query executes against the database.
- The new result is inserted into NCache.
Maintain Cached Results After Database Updates
NCache.OSS.Dapper does not automatically associate database write operations with cached query results. For example, an application may cache the following query:
var users = connection.QueryCached<User>(
"SELECT * FROM Users");
If the application later updates the database using Dapper:
connection.Execute(
"UPDATE Users SET Name = @Name WHERE Id = @Id",
new { Name = "Ali", Id = 1 });
The cached result of SELECT * FROM Users is not automatically updated or removed. A subsequent QueryCached<User> call using the same cache key can therefore return the previously cached data. Applications must maintain cache freshness through expiration, explicit cache removal, or by refreshing the query with ForceUpdate:
var users = connection.QueryCached<User>(
"SELECT * FROM Users",
options: new CacheOptions
{
ForceUpdate = true
});
Important
One database modification can affect multiple cached queries. For example, the same updated record may appear in cached results generated by different SQL queries or parameters. Because these results use different cache keys, refreshing or removing one entry does not automatically invalidate the others.
Use a Custom Cache Key
Automatic key generation is the default behavior. When an application needs to control the cache key explicitly, supply customCacheKey:
var users = connection.QueryCached<User>(
"SELECT * FROM Users WHERE IsActive = @IsActive",
new { IsActive = true },
customCacheKey: "active-users");
In this case, "active-users" is used directly and CacheKeyGenerator.GenerateCacheKey(...) is not called for the query.
Note
Use custom cache keys carefully. The application is responsible for ensuring that a custom key uniquely identifies the corresponding query result.
Use a Provider for an Individual Query
A provider can be supplied directly to an individual QueryCached<T> call:
var cache =
CacheManager.GetCache("demoCache");
var provider =
new NCacheCacheProvider(cache);
var users = connection.QueryCached<User>(
"SELECT * FROM Users",
cacheProvider: provider);
A per-call cacheProvider takes precedence over DapperNCache.CacheProvider.
Cache Key Generation
When customCacheKey is not supplied, QueryCached<T> always generates its cache key by internally calling:
CacheKeyGenerator.GenerateCacheKey(
cnn.Database,
sql,
param,
typeof(T))
CacheKeyGenerator.GenerateCacheKey has the following signature:
static string GenerateCacheKey(
string databaseName,
string sql,
object? param,
Type resultType)
The generated cache key takes the following information into account:
- Database name
- SQL query
- Query parameters
- Result type
The generated key uses the following prefix:
NCache.OSS.Dapper:
This allows QueryCached<T> to distinguish cached results produced by different databases, queries, parameters, and result types.
Handle Cache Operation Failures
By default, QueryCached<T> continues database processing when an NCache cache operation fails because CacheOptions.ErrorEnabled is false.
In this mode:
- A failed cache
Getis treated as a cache miss, and the database is queried. - A failed cache
Setdoes not prevent the database result from being returned. - A failed cache
Removedoes not preventForceUpdatefrom executing the database query.
To propagate cache-operation exceptions instead, set ErrorEnabled to true:
var users = connection.QueryCached<User>(
"SELECT * FROM Users",
options: new CacheOptions
{
ErrorEnabled = true
});
Note
ErrorEnabled controls cache-operation exceptions. It does not control exceptions raised by the database query itself.
NCache Cache Provider APIs
INCacheCacheProvider provides the cache operations used by the integration:
T? Get<T>(string key);
void Set<T>(
string key,
T value,
CacheOptions? options = null);
void Remove(string key);
NCacheCacheProvider implements these operations using NCache.
| API | NCache Behavior |
|---|---|
Get<T> |
Retrieves the cached value using the underlying NCache ICache. |
Set<T> |
Stores the value in an NCache CacheItem and applies expiration when configured. |
Remove |
Removes the specified entry from NCache. |
Dispose |
Disposes the underlying NCache ICache. |
Note
Application code normally performs caching through QueryCached<T>. The provider APIs form the cache abstraction used by the integration.