Read-Through Provider Configuration and Implementation
Note
This feature is only available in NCache Enterprise Edition.
To use Read-through caching, you need to implement the IReadThruProvider interface provided by NCache. NCache framework will use this custom implementation to read data from the back-end data source. Please refer to Configuring Read-through in Administrators' Guide for more details.
Note that if a read-through provider is specified in client.ncconf in the default-readthru-provider
tag, and has also been specified through API, the provider in API will overwrite the one specified in client.ncconf.
Note
In NCache, read-through providers are configured on cache level, i.e. for clustered caches all nodes will contain provider configurations and their deployed assemblies.
Pre-Requisites
- To utilize the APIs, include the following namespace in your application:
Alachisoft.NCache.Runtime.DatasourceProviders
Alachisoft.NCache.Runtime
Alachisoft.NCache.Runtime.Exceptions
- This should be a class library project using Microsoft Visual Studio.
- Make sure to Deploy ReadThrough Provider using NCache Web Manager.
Sample Implementation
The following code sample provides sample implementation to configure a read-through provider using the IReadThruProvider
class. The LoadFromSource() and LoadDataTypeFromSource() methods contains logic to load an object or data type respectively from the configured data source, if the object is not found in the cache.
public class SampleReadThruProvider : IReadThruProvider
{
private SqlConnection _connection;
//Perform tasks like allocating resources or acquiring connections
public void Init(IDictionary parameters, string cacheId)
{
object server = parameters["server"];
object userId = parameters["username"];
object password = parameters["password"];
object database = parameters["database"];
string connString = GetConnectionString(server.ToString(), database.ToString(), userId.ToString(), password.ToString());
if (connString != "")
_connection = new SqlConnection(connString);
try
{
_connection.Open();
}
catch (Exception ex)
{
//handle exception
}
}
// Responsible for loading an item from the external data source
public ProviderCacheItem LoadFromSource(string key)
{
// LoadFromDataSource loads data from data source
object value = LoadFromDataSource(key);
var cacheItem = new ProviderCacheItem(value);
return cacheItem;
}
//Responsible for loading bulk of items from the external data source
public IDictionary<string, ProviderCacheItem> LoadFromSource(ICollection<string> keys)
{
var dictionary = new Dictionary<string, ProviderCacheItem>();
try
{
foreach (string key in keys)
{
// LoadFromDataSource loads data from data source
dictionary.Add(key, new ProviderCacheItem(LoadFromDataSource(key)));
}
return dictionary;
}
catch (Exception exp)
{
// Handle exception
}
return dictionary;
}
// Adds ProviderDataTypeItem with enumerable data type
public ProviderDataTypeItem<IEnumerable> LoadDataTypeFromSource(string key, DistributedDataType dataType)
{
IEnumerable value = null;
ProviderDataTypeItem<IEnumerable> dataTypeItem = null;
switch (dataType)
{
case DistributedDataType.List:
value = new List<object>()
{
LoadFromDataSource(key)
};
dataTypeItem = new ProviderDataTypeItem<IEnumerable>(value);
break;
case DistributedDataType.Dictionary:
value = new Dictionary<string, object>()
{
{ key , LoadFromDataSource(key) }
};
dataTypeItem = new ProviderDataTypeItem<IEnumerable>(value);
break;
case DistributedDataType.Counter:
dataTypeItem = new ProviderDataTypeItem<IEnumerable>(1000);
break;
}
return dataTypeItem;
}
//Perform tasks associated with freeing, releasing, or resetting resources.
public void Dispose()
{
if (_connection != null)
_connection.Close();
}
private object LoadFromDataSource(string key)
{
object retrievedObject = null;
// Load item from your data source and populate retrieved Object
return retrievedObject;
}
private string GetConnectionString(string server, string database, string userName, string password)
{
string connectionString = null;
try
{
if (!string.IsNullOrEmpty(server))
connectionString = "Server=" + server + ";";
else
//Server name is empty
if (!string.IsNullOrEmpty(database))
connectionString = connectionString + "Database=" + database + ";";
else
//Database is empty;
if (!string.IsNullOrEmpty(userName))
connectionString = connectionString + "User ID=" + userName + ";";
else
connectionString = connectionString + "User ID=" + "" + ";";
if (!string.IsNullOrEmpty(password))
connectionString = connectionString + "Password=" + password + ";";
else
connectionString = connectionString + "Password=" + "" + ";";
}
catch (Exception exp)
{
// Handle exception
}
return connectionString;
}
// Deploy this class on cache
}
Additional Resources
NCache provides sample application for read-through at:
- GitHub
- Shipped with NCache: %NCHOME%\samples\dotnet\BackingSource
See Also
Using Read-Through with Cache Operations
Configuring Read-Through Provider
Write-Through Caching
Cache Startup Loader
Custom Cache Dependencies