Binary Mode
The previous topic, Serialization, discusses how Ignite.NET converts instances of user-defined types (classes and structs) to serialized form and vice versa.
Ignite also provides a way to work with the data directly in binary (serialized) form, without the need to have types present on the node or in the whole cluster. Possible use cases are:
- Some nodes have types loaded and can work with data in deserialized form, but some nodes do not have access to assemblies with types and work with data in binary format (i.e. server nodes).
- Types are not known at compile time and are constructed dynamically.
- When only a fraction of data is needed from a large object, it is faster to retrieve it in binary mode than to deserialize the whole thing.
Enabling Binary Mode
Some Ignite.NET APIs have WithKeepBinary() methods:
ICache<TK, TV>.WithKeepBinary<TK1, TV1>()ICompute.WithKeepBinary()IServices.WithKeepBinary()andIServices.WithServerKeepBinary()IDataStreamer<TK, TV>.WithKeepBinary<TK1, TV1>
These methods return a new instance of the API (current instance is not affected) with binary mode enabled which means that instead of user-defined type instances, the API will return IBinaryObject instances.
Basic Types
Note that not all types can be represented as
IBinaryObject. Primitive types,string,Guid,DateTime, collections and arrays of these types are always returned as is.
In the example below, key type int does not change because it is a primitive type.
ICache<int, Person> cache = ignite.GetCache<int, Person>("persons");
cache[1] = new Person { Name = "Joe" };
ICache<int, IBinaryObject> binaryCache = cache.WithKeepBinary<int, IBinaryObject>();
IBinaryObject binaryPerson = binaryCache[1];
string name = binaryPerson.GetField<string>("Name");
With generic APIs, it is up to the user to provide proper generic type arguments. In case when there are multiple key or value types in the cache and some of them are of basic types, use .WithKeepBinary<object, object> and then do a safety cast to IBinaryObject.
Modifying Binary Objects
IBinaryObject is immutable, call IBinaryObject.ToBuilder() method to retrieve a IBinaryObjectBuilder instance with all a copy of binary object contents. Modify data via various .Set* methods, and call Build() method to construct a new IBinaryObject instance with all the changes:
ICache<int, IBinaryObject> binaryCache = cache.WithKeepBinary<int, IBinaryObject>();
IBinaryObject binaryPerson = binaryCache[1];
string name = binaryPerson.GetField<string>("Name");
IBinaryObjectBuilder builder = binaryPerson.ToBuilder();
builder.SetField("Name", name + " - Copy");
IBinaryObject binaryPerson2 = builder.Build();
binaryCache[2] = binaryPerson2;
Creating Binary Objects
Binary objects of arbitrary type can be created from scratch without the need to have any classes/structs at hand via IBinary.GetBuilder() method. See BinaryModeExample.cs for a detailed demonstration.
IIgnite ignite = Ignition.Start();
IBinaryObjectBuilder builder = ignite.GetBinary().GetBuilder("Book");
IBinaryObject book = builder
.SetField("ISBN", "xyz")
.SetField("Title", "War and Peace")
.Build();
You can also construct instances of known types with IBinary.GetBuilder(Type) overload.
Binary Type Metadata
IBinaryObject metadata (type name, field names and types) can be retrieved with IBinaryObject.GetBinaryType() method which returns an IBinaryType instance.
For example, the following code prints out contents of an arbitrary binary object:
IBinaryObject binaryObj = binaryCache.Get(1);
IBinaryType binaryType = binaryObj.GetBinaryType();
Console.WriteLine("Object of type {0}:", binaryType.TypeName);
foreach (string field in binaryType.Fields)
{
object fieldVal = binaryObj.GetField<object>(field);
Console.WriteLine("{0} = {1}", field, fieldVal);
}
Updated almost 5 years ago
