Author: Iqbal Khan
With the explosion of extremely high transaction web apps, SOA, grid computing, and other server applications, data storage is unable to keep up. The reason is data storage cannot keep adding more servers to scale out, unlike application architectures that are extremely scalable.
In these situations, in-memory distributed cache offers an excellent solution to data storage bottlenecks. It spans multiple servers (called a cluster) to pool their memory together and keep all cache synchronized across servers. And, it can keep growing this cache cluster endlessly, just like the application servers. This reduces pressure on data storage so that it is no longer a scalability bottleneck.
There are two main ways people use a distributed cache:

Cache-aside is a very powerful technique and allows you to issue complex database queries involving joins and nested queries and manipulate data any way you want. Despite that, Read-through/Write-through has various advantages over cache-aside as mentioned below:
Read-through/Write-through is not intended to be used for all data access in your application. It is best suited for situations where you're either reading individual rows from the database or reading data that can directly map to an individual cache-item. It is also ideal for reference data that is meant to be kept in the cache for frequent reads even though this data changes periodically.
A read-through handler is registered with the cache server and allows the cache to directly read data from database. The NCache server provides a Read-through handler interface that you need to implement. This enables NCache to call your Read-through handler.
1 using System.Data.SqlClient; 2 using Alachisoft.Web.Caching; 3 4 ... 5 6 public class SqlReadThruProvider : IReadThruProvider 7 { 8 private SqlConnection _connection; 9 10 // Called upon startup to initialize connection 11 public void Start(IDictionary parameters) 12 { 13 _connection = new SqlConnection(parameters["connstring"]); 14 _connection.Open(); 15 } 16 17 // Called at the end to close connection 18 public void Stop() { _connection.Close(); } 19 20 // Responsible for loading object from external data source 21 public object Load(string key, ref CacheDependency dep) 22 { 23 string sql = "SELECT * FROM Customers WHERE "; 24 sql += "CustomerID = @ID"; 25 SqlCommand cmd = new SqlCommand(sql, _connection); 26 cmd.Parameters.Add("@ID", System.Data.SqlDbType.VarChar); 27 28 // Let's extract actual customerID from "key" 29 int keyFormatLen = "Customers:CustomerID:".Length; 30 string custId = key.Substring(keyFormatLen, 31 key.Length - keyFormatLen); 32 cmd.Parameters["@ID"].Value = custId; 33 34 // fetch the row in the table 35 SqlDataReader reader = cmd.ExecuteReader(); 36 37 // copy data from "reader" to "cust" object 38 Customers cust = new Customers(); 39 FillCustomers(reader, cust); 40 41 // specify a SqlCacheDependency for this object 42 dep = new SqlCacheDependency(cmd); 43 return cust; 44 } 45 } 46
Start() performs certain resource allocation tasks like estalishing connections to the main datasource, whereas Stop() is meant to reset all such allocations. Load is what the cache calls to read-through the objects.
Write-through handler is invoked, when the cache needs to write to the database as the cache is updated. Normally, the application issues an update to the cache through add, insert, or remove.
1 using System.Data.SqlClient; 2 using Alachisoft.Web.Caching; 3 4 ... 5 6 public class SqlWriteThruProvider : IWriteThruProvider 7 { 8 private SqlConnection _connection; 9 10 // Called upon startup to initialize connection 11 public void Start(IDictionary parameters) 12 { 13 _connection = new SqlConnection(parameters["connstring"]); 14 _connection.Open(); 15 } 16 17 // Called at the end to close connection 18 public void Stop() { _connection.Close(); } 19 20 // Responsible for saving object into external datasource 21 public bool Save (Customer val) 22 { 23 int rowsChanged = 0; 24 string[] customer = {val.CustomerID,val.ContactName,val.CompanyName, 25 val.Address,val.City,val.Country,val.PostalCode, 26 val.Phone,val.Fax}; 27 28 SqlCommand cmd = _connection.CreateCommand(); 29 cmd.CommandText = String.Format(CultureInfo.InvariantCulture, 30 "Update dbo.Customers " + "Set CustomerID='{0}'," + 31 "ContactName='{1}',CompanyName='{2}'," + 32 "Address='{3}',City='{4}'," + 33 "Country='{5}',PostalCode='{6}'," + 34 "Phone='{7}',Fax='{8}'" + 35 " Where CustomerID = '{0}'", customer); 36 rowsChanged = cmd.ExecuteNonQuery(); 37 if (rowsChanged > 0) 38 { 39 return true; 40 } 41 return false; 42 } 43 }
Start() performs resource allocation tasks like estalishing connections to the datasource, whereas Stop() is meant to reset all such allocations. Save is the method the cache calls to write-through objects.
Following sample code shows using the read-through/write-through capabilities of cache from a simple Windows application.
1 using Alachisoft.Web.Caching; 2 ... 3 4 internal class MainForm : System.Windows.Forms.Form 5 { 6 /// Fetches record from the cache, which internally accesses the 7 /// datasource using read-thru provider 8 private void OnClickFind(object sender, System.EventArgs e) 9 { 10 Customer customer; 11 Cache cache = NCache.Caches[CacheName]; 12 string key = cboCustomerID.Text.Trim(); 13 string providerName = cboReadThruProvider.Text; 14 15 customer = (Customer) cache.Get(key, 16 providerName, 17 DSReadOption.ReadThru); 18 19 ... 20 } 21 22 /// Updates the record using the cache, which internally accesses 23 /// the datasource using write-thru provider 24 private void OnClickUpdate(object sender, System.EventArgs e) 25 { 26 Cache cache = NCache.Caches[CacheName]; 27 Customer customer = new Customer(); 28 29 ... 30 31 string key = customer.CustomerID; 32 string providerName = cboWriteThruProvider.Text; 33 34 cache.Insert(key, 35 new CacheItem(customer), DSWriteOption.WriteThru, 36 providerName, null); 37 38 ... 39 } 40 }
Author: Iqbal M. Khan works for Alachisoft, a leading software company providing O/R Mapping and Clustered Object Caching solutions for .NET. You can reach him iqbal@alachisoft.com or visit Alachisoft at www.alachisoft.com.