I'm currently using an in-memory cache and looking to switch to a distributed caching mechanism with Redis. I had a look at ServiceStack's client, but the rate-limiting licensing doesn't work for me, so Booksleeve seems to be recommended.
I've set up a test program to just set and that get that same value back from Booksleeve, but it seems like the result I'm getting back isn't in my expected format, and I'm not sure what the right way to handle this is (there isn't much in the way of documentation that I can see). Here is my simple test program:
RedisConnection conn = new RedisConnection("localhost", 6379);
conn.Open();
conn.Strings.Set(1, "test", 100);
var task = conn.Strings.Get(1, "test");
task.Wait();
var x = task.Result; // byte[] result = {49, 48, 48};
var str = BitConverter.ToString(x); // string result = "31-30-30";
var l = BitConverter.ToInt64(x, 0); // Destination array is not long enough to copy all the items in the collection. Check array index and length.
As you can see, at no point do I get back the same value of "100" that I cached with my original "Set" statement. It's also interesting that I don't seem to be able to cache by numeric values (since Get and Set are members of conn.Strings). Is the recommended approach to just .ToString() all numeric key values?
Any explanation as to why I'm unable to get back the original cached value (and best practices for doing this) would be greatly appreciated.
My answer has two parts:
Redis always saves strings, even if you set a number. BUT it internally knows to do some specific actions on strings that represent numbers.
For example, if right after your first .Set() assignment you'll add:
conn.Strings.Increment(1, "test", 1);
the test key will have the value "101", which is a string, but one that is made out of an arithmetic calculation by Redis.
You need to fix your conversion function. Instead of using BitConverter, that's the right way to convert:
var str = System.Text.Encoding.UTF8.GetString(x);
var value = int.Parse(str);
Of course, this snippet doesn't include any kind of error checking, which is fairly easy to apply (e.g. what if the value is empty or contains something that is not a number).
As for your last question, is using .ToString() the recommended approach - yes. That's the way to work with Redis. But of course, you can make your own utility wrappers that take care of converting values that suppose to contian numbers, to numbers. Something like GetIntValue(string key) or so.
Related
I'm writing a sci-comp application in C# (not to be confused with comp-sci), which should accept user inputs as both real and complex numbers. This difference between possible inputs would ideally reflect in many points down the stream - if inputs are simple real numbers, I want all objects created from there onwards as simple doubles; if inputs have complex numbers, all relevant objects necessarily must be of complex numbers. (Their syntax, methods and overloads are identical)
Now, the reason why I want to do this is that, although it would be safer to assume all inputs as complex from early on, I can save on memory (and potentially processing time) if I can use double types when appropriate. I see that would consume only half the necessary memory, and arithmetic operations are simpler in these cases.
To put this simply, during run-time my code would decide what's more appropriate depending on user input, which is acceptable given that syntax is fully re-usable. I will try to outline an example using simple int and double datatypes to make this more clear:
Console.WriteLine("Enter input: ");
var input = Console.ReadLine();
bool hasValuesAfterComma = isInputFractional(input);
double myVar = Double.Parse(input); // This is executed if hasValuesAfterComma == true,
int myVar = Int.Parse(input); // Otherwise this is considered. All statements after this line work both with double or int types.
How can I set the appropriate data type during runtime?
P.S. I'm using the MathNet.Numerics package and its data types to do Linear Algebra processing.
Try dynamic variable:
dynamic myVar = hasValuesAfterComma? Double.Parse(input): Int.Parse(input);
The decoded message what was first sent using sockets to another form cannot be compared or can be but that if doesn't work. That if was just jumped every time
byte[] receivedData = new byte[1500];
receivedData = (byte[])aResult.AsyncState;
string data = encoder.GetString(receivedData);
listMessage.Items.Add("Friend: " + data);
if (data == "Friend Disconnected")
{
//this not perform
listMessage.Items.Clear();
lblHostPort.Text = "";
lblLocalPort.Text = "";
grpFriend.Visible = true;
grpHost.Visible = true;
button1.Text = "connect";
}
String comparision only works if the strings are exactly the same. An extra, missing or different whitespace. A small letter where a big one should be. Even different Unicode Normalisation - all of this and more can get in the way of it. As you are creating that string from raw bytes, even different encodings could throw a wrench into that mix.
As a general rule, string is terrible for processing and information transmissions. The only type somewhat worse is byte themself. The only advantage of string is that is (often) human readable.
But a numeric error code or even Enumeration tends to be leagues more reliable for this kind of work.
Their is 2 possibilities for you issues.
For the first one, maybe that you are not using the correct encoding in your encoder object. (difficult to say without additional information on this object.)
Encoding
Something that you can try is to check if you can get better result by using the Compare method between strings instead of the operator ==.
You will then be able to perform comparison case insensitive or with specifics options.
Again, I can't give you more information right now as you don't indicate the content of the data variable in your question.
string comparison method
I have some nodes in a collection with a Date Time:
I query this using the C# cypher client thus:
GraphClient _client = new GraphClient(new Uri(url));
DateTime dt;
_client.Cypher
.Match("(e:LineStop)")
.Where((LineStop e) => e.AddedToDataWarehouse == false && e.TimeCreated >= dt)
.AndWhere((LineStop e) => e.Duration >0)
.Return<LineStop>("e")
.Results;
This works.
How can I do the same thing using the standard web based Neo4j Graph client? I can't seem to get the syntax to work at all.
All of the existing Q&As seem to talk about structuring the data differently to be more graph like and use shortestPath. I can't do this. The data already exists. I did not design this system nor do I have the abillity to change it.
I was told by the person that did design this system (a contractor who is no longer with the company) that Neo4j now supports dates(as opposed to stringfying them). On some level it must, or else how does the C# code work, right?
The C# code is treating the Dates as strings, if you look at what is being sent over the wire (using Fiddler), you'll see the JSON has it all escaped. Importantly, it's treating it as ISO format, which is sortable. If you chose to store them using US/UK format, you'd quickly find the comparison doesn't work.
The comparison is being done by Neo4j - example cypher showing the situation you have is here:
MATCH (n) RETURN
CASE WHEN ("2017-03-19T08:12:17.9680461+00:00" > "2017-03-20T08:12:17.9680461+00:00") = true
THEN "TRUE"
ELSE "FALSE"
END
If you put that into your browser, you'll get FALSE.
Your query isn't working as you are doing a string comparison and '2017-03-17' is not the same as the actual string you have created. Of the two options below - the adding of a property is the best route - and doesn't involve changing the structure of the graph, but obviously depends on the ability to set a property on the node.
If you can't add extra properties to the objects
To do a 'Between' style approach -
You have to pass in a fully defined DateTimeOffset string example: 2017-03-19T08:12:17.9680461+00:00
To do an equality comparison (with just the date specificied)
Use STARTS WITH as #InverseFalcon said
This is awkward as a full DTOffset string is long and unwieldy :/
If you can add a property
I would add a Ticks version of the DateTime properties, i.e. have a property called TimeCreatedTicks which is simply the .Ticks property of the TimeCreated property. This is my general route for storing Dates.
For manual querying this is still a pain as you need to know the Ticks for a given date - and that (for me at least) normally involves going to LinqPad and running new DateTime(2017,3,17).Ticks.Dump()
It looks like you need a string split function:
match (l.LineStop)-[:Creates]->(ls.LineStop)
where l.Name = 'M-E' AND
split(ls.TimeCreated, 'T')[0] = '2017-03-17'
return l, ls limit 100
In this case a STARTS WITH predicate should do the trick:
match (l.LineStop)-[:Creates]->(ls.LineStop)
where l.Name = 'M-E' AND ls.TimeCreated starts with '2017-03-17'
return l, ls limit 100
Is it more efficient to use enums instead of string arrays, performance-wise?
I decided to test a particular method IsDefined, versus checking for a match-up inside a string array. I created an object of Stopwatch to test the runtime for each one.
The code, below:
Defined an enum outside of class Main:
enum Color : byte { red, blue, green }
Inside Main:
string[] colArr = new string[] { "red", "blue", "green" };
string input = "green";
Stopwatch s1 = new Stopwatch();
int loopIterations = 0;
s1.Restart();
while (loopIterations++ < 100000000)
foreach (var blah in colArr)
if (blah == input)
break;
s1.Stop();
Console.WriteLine("Runtime for foreach loop: {0}", s1.Elapsed);
loopIterations = 0;
s1.Restart();
while (loopIterations++ < 100000000)
if (Enum.IsDefined(typeof(Color), input))
continue;
s1.Stop();
Console.WriteLine("Runtime for IsDefined method returned value: {0}", s1.Elapsed);
And my output looks like this:
Runtime for foreach loop: 00:00:01.4862817
Runtime for IsDefined method returned value: 00:00:09.3421654
Press any key to continue . . .
So I wanted to ask if - assuming the code I wrote isn't, like, stupid or something - those numbers are normal, and if they are, in what way is using enums preferable to using a string array, specifically for the kind of jobs both would?
For starters, rather than performance a big reason for using enums over strings is maintainability of the code. E.g., trying to 'find all references' to Color.red can be done with a few clicks in visual studio. Trying to find strings isn't so easy. Always typing the strings is also error-prone. Although both problems could be alleviated somewhat by using constants, it's easier to use enums.
An enum can be seen as a constant integer value, which has good performance and has benefits such as using flags (masks). Comparing an int will be faster than comparing a string, but that's not what happens here. Mostly you want to do something for a specific value and you could test if(someString == "red") versus if(someColVal == Color.red), in which case the latter should be faster.
Checking if a value exists in an enum can be slower with the Enum.IsDefined, but that function has to look up the enum-values each time in this loop.
Meanwhile the first test has a pre-defined array. For the strict comparison in performance to your first test, you could do something like:
var colvalues = Enum.GetValues(typeof(Color)).Cast<Color>().ToArray(); // or hardcode: var colvalues = new[]{Color.red, Color.blue, Color.green};
var colinput = Color.red;
while (loopIterations++ < 100000000)
foreach (var blah in colvalues)
if (blah == colinput)
break;
Although as stated, finding if a value exists in an enum is normally not its primary function (mostly it's used for checking for a specific value). However it's integer base allows for other methods to check if a value is in an expected range, such as mask-checking or >, >=, < or <=
edit Seeing the comments about user input: mostly the input would be controlled, e.g.: the user is shown a menu. In a console environment that menu could be build with the numbers of the enum.
For example, enum enum Color : byte { red = 1, blue, green }, menu
1. red
2. blue
3. green
The user input would be an integer. On the other hand if typing is required, IsDefined would prevent having to retype the values and is good for ease of use. For performance the names could be buffered with something like var colvalues = Enum.GetNames(typeof(Color)).ToArray();
The normal use for enums is to represent logical states or a limited range of options: in your example, if e.g. a product ever only comes in three colours. Using a string to represent colours in such a case has two drawbacks: you may misspell the name of a colour somewhere in your code, and get hard to track bugs; and string comparison is inherently slower than comparing enums (which is basically comparing integers).
IsDefined() uses type reflection, and thus should be slower than straight string comparison. There are cases where you want to convert enums to and from strings: usually when doing input/output such as saving or restoring configurations. That's slower, but input/output is typically dominated by the slowness of storage media and networks, so it's seldom a big deal.
I know this is a very old post, but noticed the compared code snippets for the loops are not doing the looping in a similar fashion.
As in the first loop, you let the loop break once it finds the string in the string array but in the second scenario you dont let the loop stop but rather continue if the Enum.IsDefined finds the value.
When you actually let the loop in enum scenario to break if it finds the value, the enum scenario runs much faster...
I have an object with the following properties
GID
ID
Code
Name
Some of the clients dont want to enter the Code so the intial plan was to put the ID in the code but the baseobject of the orm is different so I'm like screwed...
my plan was to put ####-#### totally random values in code how can I generate something like that say a windows 7 serial generator type stuff but would that not have an overhead what would you do in this case.
Do you want a random value, or a unique value?
random != unique.
Remember, random merely states a probability of not generating the same value, or a probability of generating the same value again. As time increases, likelihood of generating a previous value increases - becoming a near certainty. Which do you require?
Personally, I recommend just using a Guid with some context [refer to easiest section below]. I also provided some other suggestions so you have options, depending on your situation.
easiest
If Code is an unbounded string [ie can be of any length], easiest semi-legible means of generating a unique code would be
OrmObject ormObject= new OrmObject ();
string code = string.
Format ("{0} [{1}]", ormObject.Name, Guid.NewGuid ()).
Trim ();
// generates something like
// "My Product [DA9190E1-7FC6-49d6-9EA5-589BBE6E005E]"
you can substitute ormObject.Name for any distinguishable string. I would typically use typeof (objectInstance.GetType ()).Name but that will only work if OrmObject is a base class, if it's a concrete class used for everything they will all end up with similar tags. The point is to add some user context, such that - as in #Yuriy Faktorovich's referenced wtf article - users have something to read.
random
I responded a day or two ago about random number generation. Not so much generating numbers as building a simple flexible framework around a generator to improve quality of code and data, this should help streamline your source.
If you read that, you could easily write an extension method, say
public static class IRandomExtensions
{
public static CodeType GetCode (this IRandom random)
{
// 1. get as many random bytes as required
// 2. transform bytes into a 'Code'
// 3. bob's your uncle
...
}
}
// elsewhere in code
...
OrmObject ormObject = new OrmObject ();
ormObject.Code = random.GetCode ();
...
To actually generate a value, I would suggest implementing an IRandom interface with a System.Security.Cryptography.RNGCryptoServiceProvider implementation. Said implementation would generate a buffer of X random bytes, and dole out as many as required, regenerating a stream when exhausted.
Furthermore - I don't know why I keep writing, I guess this problem is really quite fascinating! - if CodeType is string and you want something readable, you could just take said random bytes and turn them into a "seemingly" readable string via Base64 conversion
public static class IRandomExtensions
{
// assuming 'CodeType' is in fact a string
public static string GetCode (this IRandom random)
{
// 1. get as many random bytes as required
byte[] randomBytes; // fill from random
// 2. transform bytes into a 'Code'
string randomBase64String =
System.Convert.ToBase64String (randomBytes).Trim ("=");
// 3. bob's your uncle
...
}
}
Remember
random != unique.
Your values will repeat. Eventually.
unique
There are a number of questions you need to ask yourself about your problem.
Must all Code values be unique? [if not, you're trying too hard]
What Type is Code? [if any-length string, use a full Guid]
Is this a distributed application? [if not, use a DB value as suggested by #LBushkin above]
If it is a distributed application, can client applications generate and submit instances of these objects? [if so, then you want a globally unique identifier, and again Guids are a sure bet]
I'm sure you have more constraints, but this is an example of the kind of line of inquiry you need to perform when you encounter a problem like your own. From these questions, you will come up with a series of constraints. These constraints will inform your design.
Hope this helps :)
Btw, you will receive better quality solutions if you post more details [ie constraints] about your problem. Again, what Type is Code, are there length constraints? Format constraints? Character constraints?
Arg, last edit, I swear. If you do end up using Guids, you may wish to obfuscate this, or even "compress" their representation by encoding them in base64 - similar to base64 conversion above for random numbers.
public static class GuidExtensions
{
public static string ToBase64String (this Guid id)
{
return System.Convert.
ToBase64String (id.ToByteArray ()).
Trim ("=");
}
}
Unlike truncating, base64 conversion is not a lossful transformation. Of course, the trim above is lossful in context of full base64 expansion - but = is just padding, extra information introduced by the conversion, and not part of original Guid data. If you want to go back to a Guid from this base64 converted value, then you will have to re-pad your base64 string until its length is a multiple of 4 - don't ask, just look up base64 if you are interested :)
You could generate a Guid using :
Guid.NewGuid().ToString();
It would give you something like :
788E94A0-C492-11DE-BFD4-FCE355D89593
Use an Autonumber column or Sequencer from your database to generate a unique code number. Almost all modern databases support automatically generated numbers in one form or another. Look into what you database supports.
Autonumber/Sequencer values from the DB are guaranteed to be unique and are relatively inexpensive to acquire. If you want to avoid completely sequential numbers assigned to codes, you can pad and concatenate several sequencer values together.