Support of Memcached for .NET

CAST supports Memcached via its com.castsoftware.nosqldotnetexternal link extension. Details about the support provided for .NET source code is discussed below.

Supported Client Libraries

Library

Version

Supported

EnyimMemcached 

1.4.x

(tick)

WazMemcachedServer

1.x.x

(tick)

WazMemcachedClient

1.x.x

(tick)

CacheManager 1.2.x

(tick)

LazyCache 2.4.x

(tick)

Supported Operations

Operation Scenario Methods Supported
Select Enyim Library

Enyim.Caching.MemcachedClient.Get

Enyim.Caching.MemcachedClient.GetAsync

Enyim.Caching.MemcachedClient.ExecuteGet

Select CacheManager Library

CacheManager.Core.ICache.Get

CacheManager.Core.ICache.Exists

CacheManager.Core.ICache.Expire

Select LazyCache Library

LazyCache.AppCacheExtensions.GetOrAdd

LazyCache.AppCacheExtensions.GetOrAddAsync

Insert Enyim Library

Enyim.Caching.MemcachedClient.Store

Enyim.Caching.MemcachedClient.StoreAsync

Enyim.Caching.MemcachedClient.ExecuteStore

Insert CacheManager Library

CacheManager.Core.ICacheManager.GetOrAdd

CacheManager.Core.ICacheManager.TryGetOrAdd

Insert LazyCache Library

LazyCache.AppCacheExtensions.GetOrAdd

LazyCache.AppCacheExtensions.GetOrAddAsync

LazyCache.AppCacheExtensions.Add

Delete Enyim Library

Enyim.Caching.MemcachedClient.Remove

Enyim.Caching.MemcachedClient.RemoveAsync

Enyim.Caching.MemcachedClient.ExecuteRemove

Delete CacheManager Library

CacheManager.Core.ICache.Remove

Delete LazyCache Library

LazyCache.IAppCache.Remove

Update Enyim Library

Enyim.Caching.MemcachedClient.Increment

Enyim.Caching.MemcachedClient.IncrementAsync

Enyim.Caching.MemcachedClient.ExecuteIncrement

Enyim.Caching.MemcachedClient.Decrement

Enyim.Caching.MemcachedClient.DecrementAsync

Enyim.Caching.MemcachedClient.ExecuteDecrement

Enyim.Caching.MemcachedClient.Append

Enyim.Caching.MemcachedClient.AppendAsync

Enyim.Caching.MemcachedClient.PrependAsync

Enyim.Caching.MemcachedClient.ExecuteAppend

Enyim.Caching.MemcachedClient.Prepend

Enyim.Caching.MemcachedClient.ExecutePrepend

Enyim.Caching.MemcachedClient.Replace

Enyim.Caching.MemcachedClient.ReplaceAsync

Update CacheManager Library

CacheManager.Core.ICache.Put

CacheManager.Core.ICacheManager.Update

CacheManager.Core.ICacheManager.TryUpdate

CacheManager.Core.ICacheManager.AddOrUpdate

Objects

Icon Description

DotNet Memcached Connection

DotNet Memcached Data

DotNet Unknown Memcached Connection

DotNet Unknown Memcached Data
Link type Source and destination of link  Methods supported
belongsTo

From DotNet Memcached Data object to DotNet Memcached connection object

-
useSelectLink Between the caller .Net method object and DotNet Memcached Data object

Get

GetAsync

ExecuteGet

useInsertLink Between the caller .Net method object and DotNet Memcached Data object

Store

StoreAsync

ExecuteStore

useDeleteLink

Between the caller .Net method object and DotNet Memcached Data object

Remove

RemoveAsync

ExecuteRemove

useUpdateLink Between the caller .Net method object and DotNet Memcached Data object

Increment

IncrementAsync

ExecuteIncrement

Decrement

DecrementAsync

ExecuteDecrement

Append

AppendAsync

ExecuteAppend

Prepend

PrependAsync

ExecutePrepend

What results can you expect?

Some example scenarios are shown below:

Memcached Client Configuration

In the Memcached class file, when we add the server information by parsing the ipaddress and provide the port Number:

public MemcacedCache()
      {
         _logger = new Logger();
         var config = new MemcachedClientConfiguration();
         config.Servers.Add(new IPEndPoint(IPAddress.Parse("127.0.0.1"), 11211));
         config.Protocol = MemcachedProtocol.Binary;
         
         _cache = new MemcachedClient(null, config);
      }

In the Memcached class file, when we pass the server information as a parameter:

namespace MemcachedTryout
{
   internal class MemcacedCache : ICache
   {  const string MEMCACHE_HOST = "127.0.0.1";
      const int MEMCACHE_PORT = 14551;
      public MemcacedCache()
      {
        _logger = new Logger();
         var config = new MemcachedClientConfiguration();
         config.Servers.Add(GetIPEndPointFromHostName(MEMCACHE_HOST, MEMCACHE_PORT));
         _cache = new MemcachedClient(null, config);
      }
  ---
}

If the server information is provided in xml file:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <configSections>
    <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler,log4net" />
    <sectionGroup name="enyim.com">
      <section name="memcached" type="Enyim.Caching.Configuration.MemcachedClientSection, Enyim.Caching" />
    </sectionGroup>
  </configSections>

  <enyim.com>
    <memcached protocol="Binary">
      <servers>
         <!--put your own server(s) here-->
        <add address="127.0.0.1" port="11211" />
      </servers>
    </memcached>
  </enyim.com>

  <log4net>
    <appender name="ConsoleAppender" type="log4net.Appender.ConsoleAppender">
      <layout type="log4net.Layout.PatternLayout,log4net">
        <param name="ConversionPattern" value="%d [%t] %-5p %c %m%n" />
      </layout>
    </appender>
    <root>
      <level value="Debug" />
      <appender-ref ref="ConsoleAppender" />
    </root>
  </log4net>
</configuration>

Memcached Unknown Connection Object

In the Memcached class file, when we pass the server information as a parameter and if passed parameter is unresolved it will create Unknown Connection Object:

namespace MemcachedTryout
{
   internal class MemcacedCache : ICache
   {
      private readonly MemcachedClient _cache;
      private readonly ILogger _logger;

      public MemcacedCache()
      {
         _logger = new Logger();
         var config = new MemcachedClientConfiguration();
         config.Servers.Add(GetIPEndPointFromHostName(MEMCACHE_HOST, MEMCACHE_PORT));     
         _cache = new MemcachedClient(null, config);
      }
 ----
}

WazMemcached Library

public string MemcachedRoleName { get; set; }
public string EndpointName { get; set; }
private MemcachedClient Client
{
   get { return _client ?? (_client = WindowsAzureMemcachedHelpers.CreateDefaultClient(MemcachedRoleName, EndpointName)); }
}

Insert Operations

Enyim

  public async Task<bool> Addsync<T>(string key, T value)
      {
         _logger.Debug("Adding item to cache with key {0}", key);
         return await _cache.Store(StoreMode.Set, "Hello", value, TimeSpan.FromDays(90));
      }

CacheManager

public ValuesController(ICacheManager<string> valuesCache, ICacheManager<int> intCache, ICacheManager<DateTime> dates)
{
    _cache = valuesCache;

    dates.Add("now", DateTime.UtcNow);
    intCache.Add("count", 1);
}

Select Operations

Enyim

public async Task<T> Getsync<T>(string key)
      {
         var cacheItem = await _cache.Get<T>(Constants.num33);
        
         if (cacheItem == null)
         {
            _logger.Debug("Cache miss with key {0}", key);
            return default(T);
         }
         _logger.Debug("Cache hit with key {0}", key);
         return cacheItem;
      }

CacheManager

public IActionResult Get(string key)
{
    var value = _cache.GetCacheItem(key);
    if (value == null)
    {
        return NotFound();
    }

    return Json(value.Value);
}

LazyCache

[HttpGet]
[Route("api/dbtime")]
public DbTimeEntity Get()
{
    Func<DbTimeEntity> actionThatWeWantToCache = () => dbContext.GeDbTime();

    var cachedDatabaseTime = cache.GetOrAdd(cacheKey, actionThatWeWantToCache);

    return cachedDatabaseTime;
}

Select Operations

Enyim

public async Task<bool> Removesync(string key)
      {
         _logger.Debug("Removing item from cache with key {0}", key);
         return await _cache.Remove(Constants.key);
      }

CacheManager

public IActionResult Delete(string key)
{
if (_cache.Remove(key))
{
return Ok();
}

return NotFound();
}

LazyCache

[HttpDelete]
[Route("api/dbtime")]
public IActionResult DeleteFromCache()
{
cache.Remove(cacheKey);
var friendlyMessage = new {Message = $"Item with key '{cacheKey}' removed from server in-memory cache"};
return Ok(friendlyMessage);
}

Update Operations

Enyim

public async Task<bool> Updatesync<T>(string key, T value)
      {
         _cache.Increment("num1", 1, 10);
         
      }

CacheManager

public IActionResult Put(string key, [FromBody]string value)
{
    if (_cache.AddOrUpdate(key, value, (v) => value) != null)
    {
        return Ok();
    }

    return NotFound();
}

Known Limitations

  • In case data is not resolved, Unknown data objects are created.