Using the Redis NoSql database with .NET Part 10: a higher level of abstraction in the .NET client

Introduction

In the previous post we started looking into a Redis .NET client from ServiceStack. At this point of time there are two recommended .NET clients for Redis with ServiceStack being one and StackExchange.Redis being the other. The single biggest difference between the two is that ServiceStack.Redis requires a paid licence above a certain usage limit. The free-of-charge limit is more than enough for evaluation and testing purposes but you’ll most certainly need to buy a licence for your production environment. Otherwise if your application exceeds the free limits you’ll start to see some exception messages.

ServiceStack.Redis provides three interfaces to communicate with Redis. In the previous post we looked at the most basic one, i.e. IRedisNativeClient. It provides a wide range of low level database operations.
Most of these operations map to Redis commands like GET, SET, SMEMBERS, ZADD etc. one to one. However, the methods require string and byte array inputs and the programmer is responsible for all data conversion back and forth which results in a lot of code to achieve simple stuff.

In this post we’ll go slightly higher with the IRedisClient interface. We’ll also see how to get hold of a Redis client from Redis client manager.

The IRedisClient

The IRedisClient provides a more pleasant interface to communicate with the Redis database. Here’s an example of setting and getting a string value. The example also shows how to set multiple key-value pairs:

private static void TryRedisClient()
{
	IRedisClientsManager clientManager = new BasicRedisClientManager();
	string customerOneNameKey = "customer:1:name";
	using (IRedisClient redisClient = clientManager.GetClient())
	{
		redisClient.SetValue(customerOneNameKey, "Great Customer");
		redisClient.SetValues(new Dictionary<string, string>()
		{
			{ "someKey", "someValue" }, { "someOtherKey", "someOtherValue" }
		});
	}

	using (IRedisClient redisClient = clientManager.GetClient())
	{
		string name = redisClient.GetValue(customerOneNameKey);
		Console.WriteLine(name);
	}
}

A great improvement compared to the IRedisNativeClient interface is that we can forget the byte array arguments and return values. We can also see how to get hold of a Redis client from the BasicRedisClientManager object. BasicRedisClientManager doesn’t provide connection pooling. It creates a new client each time it is called. Connection pooling is provided by the PooledRedisClientManager object which “imposes a maximum connection limit and when its maximum pool size has been reached will instead block on any new connection requests until the next RedisClient is released back into the pool. If no client became available within PoolTimeout, a Pool TimeoutException will be thrown.” (via the documentation available here).

The client manager objects have a number of overloads to provide a host name, a port number and other parameters.

The following example shows how the Redis client exposes lists, sets and hashes via aptly named properties. There’s a property for sorted sets as well. These properties enable us to work with these data types almost as if they are native .NET lists, hash sets and dictionaries:

private static void TryVariousRedisClientCommands()
{
	IRedisClientsManager pooledClientManager = new PooledRedisClientManager(0, "127.0.0.1:6379");
	string setId = "colours";
	string listId = "to-do";
	string hashId = "customer:2";
	using (IRedisClient pooledClient = pooledClientManager.GetClient())
	{
		pooledClient.Sets[setId].Add("green");
		pooledClient.Sets[setId].Add("blue");
		var setItems = pooledClient.Sets[setId].GetAll();
		Console.WriteLine(string.Join("|", setItems));

		var toDoList = pooledClient.Lists[listId];
		toDoList.Clear();
		toDoList.Add("watch tv");
		toDoList.Add("sleep");
		toDoList.Add("write blog");
		toDoList.Add("play with kids");

		var listItems = pooledClient.Lists[listId].GetAll();
		Console.WriteLine(string.Join("|", listItems));

		string nextToDo = pooledClient.Lists[listId].Pop();
		Console.WriteLine(nextToDo);

		pooledClient.Hashes[hashId]["name"] = "New Customer";
		pooledClient.Hashes[hashId]["id"] = "2";
		pooledClient.Hashes[hashId]["address"] = "Skopje, Macedonia";

		foreach (var kvp in  pooledClient.Hashes[hashId])
		{
			Console.WriteLine(string.Concat(kvp.Key, ": ", kvp.Value));
		}


	}
}

PooledRedisClientManager has 8 overloads to provide various settings. The one in the example accepts an integer and an array of connection strings. The array is necessary in case we have a cluster of Redis servers. We provided the default connection string for demonstration purposes. The integer indicates the database number which also defaults to 0. We haven’t talked about databases in Redis yet, we’ll do that in a later post. For now it’s enough to know that databases are numbered in Redis and the numbering starts from 0. The maximum number of databases is configurable and is normally set to 16 to begin with.

The example should be easy to follow. Note how the Sets, Lists and Hashes properties are used to work with those data types. The code generates the following output:

blue|green|yellow
watch tv|sleep|write blog|play with kids
play with kids
name: New Customer
id: 2
address: Skopje, Macedonia

This client is much more convenient to work with. It hides some of the tedious low-level communication steps behind the scenes like converting the strings to jagged byte arrays. However, we still cannot work with our custom objects in an easy way. We’ll look at the IRedisTypedClient interface in the next post which solves this requirement.

You can view all posts related to data storage on this blog here.

Advertisement

About Andras Nemes
I'm a .NET/Java developer living and working in Stockholm, Sweden.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

Elliot Balynn's Blog

A directory of wonderful thoughts

Software Engineering

Web development

Disparate Opinions

Various tidbits

chsakell's Blog

WEB APPLICATION DEVELOPMENT TUTORIALS WITH OPEN-SOURCE PROJECTS

Once Upon a Camayoc

Bite-size insight on Cyber Security for the not too technical.

%d bloggers like this: