How to check if a list exists with the C# ServiceStack Redis Client

I’m wondering if there’s a method to check if a list exists on a Redis server. There is little to 0 documentation in the code.

All the redis commands have a 1:1 mapping in the IRedisNativeClient so you could use the Type() API to call the Redis TYPE command to check for the type of the key. Where it will return “list” if the key is a list or “none” if the key doesn’t exist.

The IRedisClient adds more typed, higher-level APIs to the RedisNativeClient which will let you use the GetEntryType() API to return a RedisKeyType.List enum if the key is a list or RedisKeyType.None if the key doesn’t exist.

Thank you for your quick reply. Here is an extension I wrote to perform this check.

public static bool ListExists(this RedisClient redisClient, string listID)
{
    RedisKeyType keyType = redisClient.GetEntryType(listID);
    if (keyType == RedisKeyType.List)
    {
        return true;
    }
    return false;
}
2 Likes

Here is a more generic version.

public static bool KeyExistsAsType(this RedisClient redisClient, string key, RedisKeyType keyType)
{
    bool keyExistsAsType =
    redisClient.GetEntryType(key) == keyType ? 
    true : false;
    return keyExistsAsType;
}

Cool I’d make the extension on IRedisClient as that’s what GetClient() returns, also this can be reduced to 1 line:

static bool ListExists(this IRedisClient redis, string key) => redis.Type(key)=="list";

Note: to format C# syntax in markdown you can wrap it in tripple backticks, e.g:

```csharp
//C# code
```
1 Like

Ok but is it really that much of an improvement to have:

if (redis.KeyExistsAsType(listKey, RedisKeyType.List))
{
   //..
}

Instead of:

if (redis.GetEntryType(listKey) == RedisKeyType.List)
{
   //..
}

It’s not a huge improvement but little things add up. :slight_smile:

IMO it’s not really an improvement as the wrapper ext method hides how it’s implemented so others reading your code would have to make an assumption on how it works or inspect the impl independently from its call-site from where it’s used. Also as this is a non-standard ext method they’d need to know about your APIs in addition to the standard library APIs and in order for your code to be portable they’re going to need to do a source copy + paste of your extension methods along with any redis implementations they copy.

Basically there’s some cognitive overhead in using custom extension methods so they should really be providing some value other than introducing new naming.

You’re making quite a bit of assumptions about the people likely to read my code and also how my code is structured. Others reading my code will have access to the library where it is defined so they won’t have to assume anything about how it’s implemented. All call sites have access to the underlying implementation. Any extension method I define is in a library that is easy to find and read. Portability isn’t really a big concern for me.

Extension methods are fine, but they do add some overhead so they should add some value more than wrapping existing intention revealing code behind wrappers with different naming, e.g. they’re useful in reducing boilerplate, which isn’t the case here.

if (redis.KeyExistsAsType(listKey, RedisKeyType.List))
{
   //..
}

reduces the need to do the equality comparision

if (redis.GetEntryType(listKey) == RedisKeyType.List)
{
   //..
}

That reduces boilerplate right there. I don’t want to have to write out an explicit comparison every time I want to determine if a specific key exists as a certain type. So no, it’s not just renaming existing functionality. It’s creating a more complicated function by combining smaller functions. It’s abstracting away the need to do the equality check explicitly.

Your wrapper adds an additional character so it’s not a reduction in boilerplate, but since you’re wrapping it behind an extension method it’s adding an extra callstack to each method invocation so I’m not seeing where the value is that the additional code maintenance is adding.

I’m generally all for using Extension methods when it increases readability + intent, but I’m not seeing that in this example. which is hiding the existing intention revealing implementation.

I agree. You could change it to:

redis.KeyExists(listKey, RedisKeyType.Set)

Which is fewer characters than:

redis.GetEntryType(listKey) == RedisKeyType.Set

I’ll write the full method with documentation for ya :wink: