Neo4JClient cannot retrieve Dictionary with values as objects - c#

Need help with Neo4Client, if I run fluent cypher query and use
.Return(node => node.As<Dictionary<string,string>>()) it returns both correct keys and values albeit with loss of a datatype, but if I use .Return(node => node.As<Dictionary<string,object>>()) it returns dictionary with keys, but no values that I can see. The debugger shows {object}, but I cannot cast it to anything - the field that I know is a string returns null when casting - obj as string. Same happens with Dictionary<<string, dynamic>>. What is this object and how can I retrieve my dictionary back from Neo4j using client?

Writing up the result of a Gitter conversation, and discussion here.
So this is down to the way Neo4jClient deserializes objects back, specifically the OGM (Object Graph Mapping) side of things. Basically it treats Dictionary<string, object> in a bespoke way, which in the long run Activates a new object instance, hence the objects actually being object instances, and not a string or equivalent.
There's no way (at present) around this without changing the OGM side of things substantially.

Related

Recursively remove key from Generic C# Object

I am trying to visualize a C# object which is a SyntaxTree. JSON would be nice, but not required, I am just having a hard time dealing with the VS UI and all the circular references in the object. when I try to use JSON.NET to serialize it, I get a circular reference error. This isn't the first time I have run into a similar problem, but I thought I would work on it for a bit.
I know which keys need to be removed, they are ContainingElement, ContainingNamSpace, ContainingSourceUnit, ContainingType.
I was trying to create a function that could be reused to recursively remove those keys from the object before I pass it to JSON.NET, but I need some help.
public static object removeObjectsByName(object incoming, string WildcardRemove){
List<object newObject = new List<object>();
foreach (var item in incoming)
{
if (subItem.ToString().Contains(WildcardRemove))
{
continue;
}
}
removeObject(newObject);
return newObject;
}
I don't typically do a lot with generic types, but I don't know what all the incoming types of data will be, especially as we call it recursively. Should we create a List, Array, or leave it an object? Here is a sample of what I am looking at:
The root of the object is named tree, I am specifically interested in the Functions which has 61 items in the array. As you dig into those you start to find the Containing* keys that need to be removed. Trouble is that they will also exist under Body and Properties. Then under Body, there is another Properties which will have it's Containing*.
I don't need any of that back referencing stuff, I just want each child without any keys named Containing*.
Any tips? Again, I don't care if the output is JSON, to the Console, as a List, if we use Linq or what, just trying to see my way through this.

How can I maintain C# primitive types above RedisValue when using StackExchange.Redis

I started using the StackExchange.Redis client for storing key value pairs.
I have a nested dynamic object (JObject) and I flatten that object to a key-value structure that looks something like:
Lets assume the JObject looks like:
"Root":
{
"Obj1":
{
"Prop":12,
"Prop2": "StringValue"
}
}
I flatten this object into a Dictionary<string, object> that generates key value pairs that look like:
key: "Root.Obj1.Prop" | value: 12
key: "Root.Obj1.Prop2" | value: "StringValue"
I'm using object and not string since my client knows how to handle various primitives (which aren't always strings).
The specific redis client excepts a RedisValue struct which has implicit castings for multiple types but not from object.
So I had to split my dictionary into different primitive enumerables in order to create RedisValues and to "maintain" their original types:
var strs = dic.Where(kvp => kvp.Value is string).Select(kvp => new HashEntry(kvp.Key, (string)kvp.Value));
var ints = dic.Where(kvp => kvp.Value is int).Select(kvp => new HashEntry(kvp.Key, (int)kvp.Value));
Now each value in the ints enumerable has a IsInteger property equal to true.
So after setting redis with those values, I'm now fetching the key-values from Redis and I have a bunch of RedisValues in my hand. I take one RedisValue which had a IsInteger property equal to true and see that it didn't really maintain that state.
My questions:
Is there any way I can maintain the real primitive types between sets and gets? I understand I have some boxing\unboxing issues by keeping them as
objects but I have lot's of benefit's in this specific app. Using a RedisValue struct isn't something that I'd like to do across my application. I'd like to keep that in a small specific layer that communicates with Redis.
If theres no way to do (1) then is there any good reason why the RedisValue doesn't keep the IsInteger property between sets and gets? When I set the RedisValue I have the IsInteger property set to true and when I fetch it, it's false.
Thank you.
You could write an additional key per property with type information, e.g.
Root:Obj1:Prop=12
Root:Obj1:Prop:type=int
Root.Obj1.Prop2=StringValue
Root.Obj1.Prop2:type=string
and always retrieve the type key first so that you know how to convert the value key.
But I wouldn't recommend it. Instead, I'd recommend one of two standard approaches, depending on how you intend to query the data via Redis.
Map strongly typed objects to Redis keys
Assumes that efficient querying via Redis operations is a priority
Allows you to localise your Redis specific code in a mapping class
Store a persisted object
Basically a BLOB of data. Could be a complete JSON object (perhaps even including full type information for each property - there's an option to enable that with Json.Net) or an array of bytes using protobuf
Assumes you're using Redis just for storage; which is OK

Use ASP ScriptingContext Request collections in C#?

I am trying to use request elements from an ASP application in a .NET class library that is used in the application. I came across a head scratcher that I can't wrap my head around:
//Context is an ASPTypeLibrary.ScriptingContext
dynamic req = System.EnterpriseServices.ContextUtil.GetNamedProperty("Request");
Context.Response.Write(req.Form("mykey")); //this writes the value I expected
Context.Response.Write(String.Format("{0}", req.Form("mykey"))); //this writes 'System.__ComObject'
Am I going about this all wrong? I was using info I gleaned from this question.
You should note that Request.Form("someKey") is not a string. The source of your confusion, however, originates not in Request.Form("someKey") but on the other side, in Response.Write(...).
There are some automatic conversion shenanigans going on.
Request.Write(...) doesn't take a string. It takes a Variant. The method will do its darnest to output whatever you pass to it.
If the Variant holds a BSTR (a COM string), it will output that unchanged. It will also try calling VarChangeTypeEx(...) (kind-of; see note below) to try to see if it can get COM to convert it to a BSTR (that's what happens when you pass it a number). If the Variant contains an object with a default method on it ([propvalue]), and it has no better way to output it, it will call the default method and start over with the result of that. I think it has a few other tricks up its sleeve, which are not entirely clearly documented.
At a high level, it should now be clear what's happening. On the first line, req.Form("myKey") returns a COM object, which then gets passed down to Response.Write(...), which then converts that object to a BSTR string and outputs it. On the other hand, when you try to pass req.Form("myKey") to a C# method, the conversion doesn't occur and you get a generic COM object instead, with predictable consequences.
So what is the return value of Request.Form("someKey") then? It's an IRequestDictionary object. And why a dictionary? Because you can submit an http request that has multiple form elements with the same name. This can be the case, for example, when the input elements are checkboxes intended to be overlapping options.
What happens when the form has multiple entries? The conversion process returns a joined string analog to String.Join(", ", someArray) in C#.
It's not clear to me whether Response.Write has intimate knowledge of IRequestDictionary (unlikely), or whether it knows about COM Enumerator pattern (more likely) and it enumerates them to compose the string.
More interesting to me is who is responsible for the conversion process, because VBScript's CStr() will do the same conversion. I had always assumed that CStr() was a thin wrapper around VarChangeTypeEx(...), but I'm pretty sure that VarChangeTypeEx(...) does not concatenate enumerators like that. Obviously CStr() is a lot fancier than I had assumed. I believe that Response.Write simply calls internally whatever API fully implements CStr() and relies on that for the conversion.
For further exploration of the Classic ASP objects and interface, try http://msdn.microsoft.com/en-us/library/ms524856(v=vs.90).aspx instead of the usual VBScript-based descriptions.

How do I compare a list of dictionaries for equality in C#

I'm trying to compare 2 objects expectedItems and resultItems of type IEnumerable<IDictionary<string, object>> but haven't been able to do much with it.
Also, one dictionary is initialised in the code, and the other one is built from a JSON response from an external API. Since, JSON doesn't really care about the order of the properties within the object, a SequenceEquals is ruled out.
I do have two equal objects and all of these understated methods are failing,
First,
CollectionAssert.AreEqual(expectedItems, resultItems)
Second,
var expectedItems = entries.Select(e => e.Serialize()).ToList();
resultItems.Zip(expectedItems,(objects, dictionary) =>
objects.OrderBy(pair =>pair.Key).SequenceEqual(dictionary.OrderBy(pair => pair.Key)))
.Should()
.NotContain(false);
The objects (as far as I see) are equal.
Any thing that I can try, or anything that I am currently doing wrong?
EDIT
The API trims the tick count from the timestamp that's why the failure. How can I trim the timestamp in the expectedItems dictionary and then compare? So, the collections have to be same and the comparison for timestamp needs to be overridden. Anyone?
Two things to check:
Are the object implementing preperly the Equals() method? If not the equality just check for the reference, and since they are two different instance they appear to be different.
Another option could be, since your object is representing a Timestamp, as I guess by the picture.
even if it properly implements Equals, are the objects the same even in term of the millisecond ( if existing ) portion?
Why don't you install FluentAssertions and do something like this?
resultsItem.ShouldAllBeEquivalentTo(expectedItems);
I don't know by heart how restrictive the DateTime comparison is, but you can easily override the behavior for a particular property.

What is the best way to tell if an object is modified?

I have an object that is mapped to a cookie as a serialized base-64 string. I only want to write out a new cookie if there are changes made to the object stored in the cookie on server-side.
What I want to do is get a hash code when the object is pulled from the cookie/initialized and compare the original hash code to the hash code that exists just before I send the cookie header off to the client to ensure I don't have to re-serialize/send the cookie unless changes were made.
I was going to override the .NET's Object.GetHashCode() method, but I wasn't sure that this is the best way to go about checking if an object is modified.
Are there any other ways I can check if an object is modified, or should I override the GetHashCode() method.
Update I decided to accept #rmbarnes's answer as it had an interesting solution to the problem, and because I decided to use his advice at the end of his post and not check for modification. I'd still be interested to hear any other solutions anyone may have to my scenario however.
GetHashCode() should always be in sync with Equals(), and Equals() isn't necessarily guaranteed to check for all of the fields in your object (there's certain situations where you want that to not be the case).
Furthermore, GetHashCode() isn't guaranteed to return unique values for all possible object states. It's conceivable (though unlikely) that two object states could result in the same HashCode (which does, after all, only have an int's worth of possible states; see the Pigeonhole Principle for more details).
If you can ensure that Equals() checks all of the appropriate fields, then you could possibly clone the object to record its state and then check it with Equals() against the new state to see if its changed.
BTW: Your mention of serialization gave me an idea. You could serialize the object, record it, and then when you check for object changing, repeat the process and compare the serialized values. That would let you check for state changes without having to make any code changes to your object. However, this isn't a great solution, because:
It's probably very inefficient
It's prone to serialization changes in the object; you might get false positives on the object state change.
At the end of the object's constructor you could serialize the object to a base 64 string just like the cookie stores it, and store this in a member variable.
When you want to check if the cookie needs recreating, re - serialize the object and compare this new base 64 string against the one stored in a member variable. If it has changed, reset the cookie with the new value.
Watch out for the gotcha - don't include the member variable storing the base 64 serialization in the serialization itself. I presume your language uses something like a sleep() function (is how PHP does it) to serialize itself, so just make sure the member is not included in that function.
This will always work because you are comparing the exact value you'd be saving in the cookie, and wouldn't need to override GetHashCode() which sounds like it could have nasty consequences.
All that said I'd probably just drop the test and always reset the cookie, can't be that much overhead in it when compared to doing the change check, and far less likelyhood of bugs.
I personally would say go with the plan you have.. A good hash code is the best way to see if an object is "as-is".. Theres tons of hashing algorithms you can look at, check out the obvious Wikipedia page on hash functions and go from there..
Override GetHashCode and go for it! Just make sure ALL the elements of the information make up part of the hash :)
Seems odd to me why you'd want to store the same object both server side and client side - especially if you're comparing them on each trip.
I'd guess that deserializing the cookie and comparing it to the server side object would be equivalent in performance to just serializing the object again.
But, if you wanted to do this, I'd compare the serialized server side object with the cookie's value and update accordingly. Worst case, you did the serialization for naught. Best case, you did a string compare.
The alternative, deserializing and comparing the objects, has a worst case of deserializing, comparing n fields, and then serializing. Best case is deserializing and comparing n fields.

Categories