Component Documentation : Cross-Language Clients User Guide : BigMemory .NET Client : Using the .NET Client API
Using the .NET Client API
This section covers connecting to, working with, and searching your BigMemory data. For the complete class library documentation, refer to the API documentation in the /apis/csharp/apidoc-csharp.zip directory of the kit.
Connecting with the CL Connector
Your application will communicate with the CL Connector via the ICacheManager interface.
Begin by creating a Configuration object. For a deployment where the BigMemory Client is located on the same machine as the CL Connector, use a configuration with the Nirvana Shared Memory (SHM) transport:
Configuration cfg=new Configuration("/dev/shm", 16));
For a deployment where the BigMemory Client and the CL Connector are located on different machines, use a configuration with the Nirvana socket transport. For example, here we create a configuration that connects to the local host at the default port, uses Nirvana socket transport, and provisions a pool of 16 connections to share:
Configuration cfg=new Configuration("localhost",
Constants.defaultPort, TransportType.NIRVANA, 16);
Notice that configurations with different transport types require different parameters:
*Nirvana Shared Memory (SHM) - Configuration("SHMLocation", clientPoolSize) - generally used when the BigMemory Client is located on the same machine as the CL Connector.
*Nirvana socket - Configuration("hostName", portNumber, TransportType.NIRVANA, clientPoolSize) - used when the CL Connector and the BigMemory Client are located on different machines.
Once you have your Configuration instance ready, create an ICacheManager using the Xplatform.CreateCacheManager static method:
ICacheManager cachemanager = XPlatform.CreateCacheManager(cfg);
Shutting the connection down
The ICacheManager needs to be closed in order for it to release all resources (like connections). Close it by invoking the Close() method on it:
cachemanager.Close();
Accessing a Cache
Once you've obtained a reference to your ICacheManager, it is now connected to your CL Connector and will let you access any Cache known by the CL Connector.
To retrieve a thread-safe instance of a Cache, you will need its name, the type of the key, the value, and a serializer for those types.
Serializers
The protocol recognizes the following types:
*bool: A boolean value (true or false), one byte
*byte: A signed byte
*i16: A 16-bit signed integer
*i32: A 32-bit signed integer
*i64: A 64-bit signed integer
*double: A 64-bit floating point number
*byte[]: An array of bytes
*string: Encoding agnostic text or binary string
If you want to send complex types to the CL Connector, you will have to provide a serializer that can serialize your complex key and value types for a Cache.
Say we have the following Class, which is our Value type:
public class User
{
public long Id { get; set; }
public string Login { get; set; }
public string Email { get; set; }
}
We store these keyed to the login, as a string. We now need to provide a serializer like this:
public class UserCacheSerializer : ICacheSerializer<string,User>
{

public Value SerializeKey(string key)
{
Value v = new Value();
v.StringValue = key;
return v;
}

public string DeserializeKey(Value serializedKey)
{
return serializedKey.StringValue;
}

public StoredValue SerializeValue(User objectValue)
{
Dictionary<String, Value> nvpairs = new Dictionary<string, Value>();

Value idval = ValueHelper.NewValue(objectValue.Id);
nvpairs["id"] = idval;

Value emailval = ValueHelper.NewValue(objectValue.Email);
nvpairs["email"] = emailval;

StoredValue sv = new StoredValue();
sv.Value = ValueHelper.NewValue(Encoding.Unicode.GetBytes(objectValue.Login));
sv.Nvpairs = nvpairs;
return sv;

}

public User DeserializeValue(StoredValue serializedValue)
{
User user = new User();
user.Login = Encoding.Unicode.GetString(serializedValue.Value.BinaryValue);
user.Id = serializedValue.Nvpairs["id"].LongValue;
user.Email = serializedValue.Nvpairs["email"].StringValue;
return user;
}
}
Note that both serialize and deserialize methods (whether for key or value) are kept symmetric.
StoredValue is composed of the actual Value (in this example, the byte array representation of the user's login). StoredValue can hold entire object graphs serialized with whatever serialization strategies fits your needs. It also holds an arbitrary amount of name/value pairs. The names are String, while the values are of type Value. You can use these name-value pairs to store whatever you want. Note that these name-value pairs also become indexable and searchable using the search API.
A byte array is not indexable, however it can be used within name-value pairs. In the above example, both user id and email are stored as byte arrays. Even though byte arrays are not indexable, search can be enabled on the attributes. Since we use the login as the key in our use case, storing that as a binary representation within the "default unindexed value" is good enough.
Special handling for DateTime objects
C# captures date information with more precision than Java does, which means the string representation has parts that Java is not prepared to parse. There are two parts to handling this. First, use the IsoDateTimeConverter for the C# side serialization and deserialization code. Second, trim C# DateTime objects to millisecond granularity. You can do this via the Terracotta.Ehcache.Utilities.DateUtility.TrimToMillisGranularity(DateTime dt) method. It returns a new DateTime object trimmed appropriately. Alternatively, you can use ValueHelper.newValue(..) on a DateTime object to do the trimming for you.
Key-based store and retrieve
Now that we have defined an ICacheSerializer for our cache, we can retrieve the cache from the ICacheManager. The example below assumes that we have defined a cache named "userCache" within the ehcache.xml file used to configure the CL Connector.
// create a serializer
ICacheSerializer<string, User> serializer = new UserCacheSerializer();

// get a cache
ICache<string, User> users = cachemanager.GetCache("userCache", serializer);

// make a user
User user1 = new User();
user1.Id = 1;
user1.Email = "someone@somewhere";
user1.Login = "secretpasswd";

// put the user
users.Put(user1.Login, user1, ConsistencyType.STRONG);
The following is an example if you were using the BSON code sample for .NET (Recipe2 is the class defining the domain object, and Recipe2BsonSerializer() is the serializer class).
ICache<string, Recipe2> cache = cacheManager.GetCache("TestCache",
new Recipe2BsonSerializer());
cache.Put(rec.Name, rec, ConsistencyType.STRONG);
The ConsistencyType attribute sets the consistency, strong or eventual, with which you expect the CL Connector to execute an operation. For more information, refer to Consistency.
To retrieve by key, invoke the get method:
User someUser = userCache.Get(someLogin, ConsistencyType.EVENTUAL);
To retrieve in C#:
Recipe2 rec = (Recipe2)cache.Get(args[1], ConsistencyType.EVENTUAL);
Compare and Swap (CAS) Operations
The following CAS operations are provided in C#:
*PutIfAbsent(TKey, TValue) - Puts the specified key/value pair into the cache only if the key has no currently assigned value. Unlike Put, which can replace an existing key/value pair, PutIfAbsent creates the key/value pair only if it is not present in the cache.
*Remove(TKey, TValue) - Conditionally removes the specified key, if it is mapped to the specified value.
*Replace(TKey, TValue) - Maps the specified key to the specified value, if the key is currently mapped to some value.
*Replace(TKey, OldValue, NewValue) - Conditionally replaces the specified key's old value with the new value, if the currently existing value matches the old value.
For more information about atomic operations and cache consistency, refer to Consistency.
Search
This section provides an overview of how to do cross-language searches of PNF data stored within BigMemory. More detailed information may be found on the BigMemory Max Developer Guide.
In order to search BigMemory data, you first need to add the <searchable/> tag to the cache configuration in your ehcache.xml file.
<ehcache>
(...)
<cache name="userCache">
(...)
<searchable/>
</cache>
</ehcache>
This configuration will scan all keys and values in the cache and, if they are of supported search types, add them as search attributes. Values of the Name/Value pairs in the PNF's StoredValue sent to the CL Connector, other than of type byte[], can all be indexed and made searchable. (Continuing with the example of the previous section, this would mean id and email.)
You can also add search attributes using the provided attributeExtractor class, for example:
<ehcache>
(...)
<cache name="userCache">
(...)
<searchable>
<searchAttribute name="email" class="net.sf.ehcache.xplatform.search.Indexer"/>
</searchable>
</cache>
</ehcache>
To perform a query, use the Cache.query(String) method, providing a BigMemory SQL query string, for example:
SearchResults<string, User> result = userCache.Query("select * from userCache
where email ilike '%@terracottatech.com'");
For more information about how to construct BigMemory SQL queries, see "Searching with BigMemory SQL" in the BigMemory Max Developer Guide.
Note:  
Note: Java (POJO) data stored within BigMemory can also be searched using the native Ehcache Search API, which is documented on the BigMemory Max Developer Guide.
Copyright © 2010-2017 Software AG, Darmstadt, Germany.

Product LogoContact Support   |   Community   |   Feedback