I am new to redis and I wonder how to send a class or a struct with StackExchange.Redis.
So lets assume I want to write
var redis = ConnectionMultiplexer.Connect("localhost");
var db = redis.GetDatabase();
db.StringSet(key, value);
This is actually only possible if my value is primitive. So is there any other way to achieve sending complex types without serializing them as json?
Since Redis is not aware of your class or struct, you'll need to define how to store it. A recommended way is to store the object as a hash, where the key is the property name, and the value is the property value. Note that this does not support object graphs, e.g. nested collections or complex types.
As per the documentation on data types:
A hash with a few fields (where few means up to one hundred or so) is stored in a way that takes very little space, so you can store millions of objects in a small Redis instance.
Alternatively, you could serialize the object yourself and store it as a string/byte[]. Json is one format, which includes the property names in the data, which is great for versioning. E.g. if a new property is added, you wouldn't need to go and change all existing data. The downside is that it takes up a lot of space. You could use any other form of serialization as well, e.g. binary serialization.
Related
I am implimenting an existing cache interface (for Redis) within a legacy code base (I am unable to refactor it to be more appropriate), the interface doesn't specify any type information for example:
interface ICache {
object Get(string key);
void Set(string key, object item);
}
With version 1.2 of StackExchange.Core you have to specify the type when storing/retreiving from the database - which I don't have.
Currently I feel like I am hacking around the problem, I store all objects as serialized strings, then use Json.net to Deserialize based on the $type information.
Is there a more appropriate solution to my problem, that doesn't involve changing the interface?
No that's totally cool. Redis can store values as string or byte array only anyways, at least for normal string or hash.
And if you don't know the type upfront, you have to help yourself and work with a separated field in Redis which stores the value. You use the $type field, Newtonsoft.Json generates I guess? I'm using a separated field on a hash where I store the value, type and other meta information...
When you deserialize the value, you have to know the concrete type, and the only way to know that, is the assembly qualified type information you have stored.
I use the same for http://cachemanager.net.
You can optimize it though. It is not necessary to always serialize an object which actually costs some performance. For scalar values and strings, you could just store the value and the type information within a hash, and cast it, instead of deserializing it. That's what I do at least, and the performance gain is pretty significant.
That being said, if you store POCOs only anyways, it doesn't matter.
I want store collection of complex c# class in Redis
This collection has 2 type of usage:
first retrieve all objects from collection
second is retrieve specific item from collection by id
What is the best Redis type for storing this type of data?
Is it Ok to store c# object as byte array in Redis String, and when i need to this data deserialize it to my collection? , also if the rate of this data usage is high.
Dose exist any better solution for cache data for c#?
You can use Redis Hashes for your C# objects. Populate it with HMSET:
HMSET objects:classname:id member1type member1value [member2type member2value]...
To get all objects, simply use HGETALL, and to get a specific member, HGET (you can also use HMGET to get more than one member).
Depands on your needs, you can also add sets with ids for each class, and than use SORT to get a specific member(s) from all stored class objects.
I have defined a class and i need to store some objects of that class for future reference. Can i store these objects into an azure database i've created ?
In order to save an object (instance of a Class) to whatever medium (SQL Server, Azure SQL Database, Azure Table Storage, Blob Storage, local File System, whatever you come up with), you will need to serialize it. Then store the result of serialization to the medium of your choice. Next, when you want to use the persisted state of the object, you will have to deserialize it.
There are different serialization formatters, like XML, JSON, Binary, etc. Which one to use, depends on the where and how you are going to store the object. The most important however, is that, in order one object to be serialized, the defining Class should be marked with SerializableAttribute. And the drama begins when you want to serialize object which is part of 3rd partys API.
If it is your type - just mark it as Serializbale, serialize and store it. Pretty stright-forward process.
If you don't have access to the source code to explicitly mark class as Serializable, you could possibly use the Serialization Surrogate to serialize your object. But, you might have issues when deserializing. For example, if the API Class you use does not have a public contructor. Or if it does not provide setters for some of the properties, etc., etc. At the end, if a Type is not designed to be serializable, and is part of 3rd party API, there might be a ton of reasons serialization/deserialization might fail.
At the end, you could try using the Json.NET serializer (install via NuGet):
var someObj = new DummyClass
{
ID = Guid.NewGuid(),
IntID = 102934,
Name = "My Super Hero Name"
};
string json = JsonConvert.SerializeObject(someObj);
Console.WriteLine(json);
var otherObj = JsonConvert.DeserializeObject<DummyClass>(json);
Console.WriteLine(otherObj.ID);
Console.ReadKey();
and check if it correctly serializes/deserializes your object. If everything is fine - use the json string to save it into Database of your choice.
I have a predefined data format, which requires me to have an object like this:
settings:{
settingA:'someValueFromSql',
settingB:'someValueFromAD'
settingC:'someValueFromConfigFile',
settingD:'someValueFromReflection',
settingE:42,
...
}
This settings object is in fact a huge mess of data stitched together from many different sources, but this is how the data is expected by the frontend. I'd like to put the "get/process all data from one source" in a function each, and tape the object together in the end.
So I would have one object
sqlSettings:{
settingA:'someValueFromSql',
settingG:'someOtherValueFromSql',
...
}
returned by function a, and an object
adSettings:{
settingB:'someValueFromAD',
settingV:'someOtherValueFromAD',
...
}
returned by function b, and an object
settings includes adSettings, sqlSettings
where, with at most two simple steps, I can "join together" both objects into a flat third object.
Is this possible with fixed-size objects, without using a generic Dictionary, or am I barking up the wrong tree?
(I'm sure this question was already asked on SO, but I guess I don't find the right words)
It's not possible with a "normal" object, but you can do it with an ExpandoObject and the dynamic keyword. But you need at least .net 4.0
dynamic settings = new ExpandoObject();
//If you try to assign a property that doesn't exist, it is added to the object.
settings.SettingA="sfgd"
Anyway I discourage using this approach. why you don't want to use a IDictionary<string, object> or better a IDictionary<string, MyCustomSettingObject>
--------------------UPDATE---------------------
if the only thing that stops you from using a dictionary is the serialization you can implement the IXmlSerializable Interface and ouput the xml you like:
Proper way to implement IXmlSerializable?
If those partial setting objects have fixed size (meaning fixed number of properties), then you can definitely create a flat object with e.g. only properties to fit all the values in. Then to ease your work, you can try to use Automapper to map the partial objects to the "grouped" object.
http://automapper.codeplex.com/
Otherwise, you will have to stick with the dictionary.
I am warpping an ArcGIS IFeature object with a class that has my required properties to get and set them easily.
Basically, the get and set operations just use feature.get_value(index) and feature.set_value(indes, value), and expose the strongly typed value.
I have several fields that use a domain (basically, an IDictionary<string, object>) to represent common properties across the application.
At first I figured I would only use the keys of the domain (which are normal int values) in my wrapping class, and use the domain in my ToString() method, to translate to strings for the UI.
Later I figured out I can use strings in my applicaiton (which makes it easier to pass around nulls, as the actual domain fields are nullable most of the time), and only change those fields' getters and setters to use GetDomainValue(index) and SetDomainValue(index, value) method that will translate between the key and value to/from the underlying feature object.
What approach do you think is better? I figured the string approach is a bit more "persistent ignorant", as my class doesn't care how the values are being saved, just their string representation.
On the other hand, it makes the code jump through loops a bit - instead of returning what's in the feature, every getter needs to iterate the domain.
You might want to think about representing your domain fields with Nullable< Int32>. This would give you a way to represent features that have a domain value specified but it also allows you to directly specify null where appropriate.
I ended up sticking with the domain values, so that I can also verify that the calling code passed a valid value.