Using the Redis NoSql database with .NET Part 11: working with objects in the .NET client

Introduction

In the previous post we looked at the IRedisClient interface to communicate with Redis. We saw that it provides a more convenient way of dealing with Redis commands in code. It’s especially useful when working with lists, hashes, sets and sorted sets since those data types are exposed through properties. We can then process those variables almost like we do with their .NET equivalent objects, i.e. dictionaries, lists and hashsets. We also briefly looked at the two Redis client manager classes that provide access to a new Redis clients.

We still cannot seamlessly work with our custom objects. We’re still responsible for serialising and deserialising them through e.g. JSON. This is where the generic IRedisTypedClient enters the scene. We’ll look at that in this post.

Working with objects in Redis

Consider the following Person and Address object hierarchy:

public class Person
{
	public int Id { get; set; }
	public string Name { get; set; }
	public bool IsFriend { get; set; }
	public Address Address { get; set; }
}

public class Address
{
	public string Street { get; set; }
	public string City { get; set; }
	public int Number { get; set; }
}

Dealing with objects insertions and selections using the methods and functions we’ve looked at so far would be pretty cumbersome. So let’s see how the generic solution works. The IRedisTypedClient interface has a typed parameter where the T is the type we want to work with, such as Person in our example. An instance of an object that implements the interface can be extracted using the As function of IRedisClient. IRedisClient and IRedisTypedClient are very similar but the functions in IRedisTypedClient work with the specified type.

Here’s an example of saving a new Person object and retrieving it by ID:

private static void TryRedisTypedClient()
{
	IRedisClientsManager pooledClientManager = new PooledRedisClientManager(0, "127.0.0.1:6379");
	using (IRedisClient pooledClient = pooledClientManager.GetClient())
	{
		//save a new Person object
		IRedisTypedClient<Person> personClient = pooledClient.As<Person>();

		long nextId = personClient.GetNextSequence();
		Person person = new Person()
		{
			Id = Convert.ToInt32(nextId),
			IsFriend = true,
			Name = "Elvis Presley",
			Address = new Address() { City = "Memphis", Number = 1, Street = "Graceland" }
		};
		Person savedPerson = personClient.Store(person);

		//retrieve person by ID
		Person retrievedPerson = personClient.GetById(nextId);
		Console.WriteLine("Retrieved person by ID: ");
		Console.WriteLine(string.Concat("Name: ", retrievedPerson.Name, ", ID: ", retrievedPerson.Id, ", is friend: "
			, retrievedPerson.IsFriend, ", address city: ", retrievedPerson.Address.City));
	}
}

IRedisClient exposes the generic As method where we specify that we want to work with the Person object. IRedisTypedClient keeps track of the most recent ID of the given object type and can generate a new one using the GetNextSequence function. It returns a new integer ID as an Int64. We convert it to an Int32 as most IDs in domain objects tend to be integers but this is really up to you to handle as you wish. We then build a new person and attach an address to it. The Store function saves the object and returns the saved object.

Retrieving an object by ID is equally easy, we just call the GetById function.

If everything goes fine then we get the following output in the console:

Retrieved person by ID:
Name: Elvis Presley, ID: 1, is friend: True, address city: Memphis

There’s no specific update function, we use Store for that purpose as well:

IRedisClientsManager pooledClientManager = new PooledRedisClientManager(0, "127.0.0.1:6379");
using (IRedisClient pooledClient = pooledClientManager.GetClient())
{
	IRedisTypedClient<Person> personClient = pooledClient.As<Person>();
	Person elvis = personClient.GetById(1);
	elvis.Address.City = "Heaven";

	Person savedPerson = personClient.Store(elvis);

	Person retrievedPerson = personClient.GetById(1);
	Console.WriteLine(string.Concat("Name: ", retrievedPerson.Name, ", ID: ", retrievedPerson.Id, ", is friend: "
		, retrievedPerson.IsFriend, ", address city: ", retrievedPerson.Address.City));
}

We retrieve the person by its ID, modify its properties and save the updated object.

Here’s the output:

Name: Elvis Presley, ID: 1, is friend: True, address city: Heaven

Deletion by ID is equally easy with the DeleteById function:

personClient.DeleteById(1);

IRedisTypedClient is a large interface with more than 160 functions in it. You can explore them in Visual Studio. Most function names are very descriptive like GetAllEntriesFromHash, GetAllItemsFromSortedSetDesc, MoveBetweenSets or PopItemWithLowestScoreFromSortedSet. It also exposes the Lists, Sets, SortedSets and Hashes properties that we saw in the previous post. Hence if you want to store the customers in a list then it’s very straightforward.

The more interesting question is how these objects are inserted into Redis. After all we saw before that Redis has very little of the strictness of relational databases with schemas, auto-incrementing IDs, primary keys etc. How are Person objects handled then? How is the ID generated? We’ll see that in the next post where we diverge a little from the .NET client and look at how to monitor the incoming commands into the Redis database.

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 )

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: