[CSHARP-44] Dictionary objects fail as long as the key is not of type string (or some base type) Created: 18/Jun/10 Updated: 02/Jun/11 Resolved: 19/Jun/10 |
|
| Status: | Closed |
| Project: | C# Driver |
| Component/s: | None |
| Affects Version/s: | None |
| Fix Version/s: | None |
| Type: | Improvement | Priority: | Minor - P4 |
| Reporter: | nisbus | Assignee: | Craig Wilson |
| Resolution: | Won't Fix | Votes: | 0 |
| Labels: | None | ||
| Remaining Estimate: | Not Specified | ||
| Time Spent: | Not Specified | ||
| Original Estimate: | Not Specified | ||
| Environment: |
All |
||
| Description |
|
This method: public object CreateDictionary(Document document) { return document.ToDictionary(pair => (TKey)Convert.ChangeType(pair.Key, typeof(TKey)), pair => (TValue)pair.Value); }Will fail for all Dictionary types that have a key of any value other than string. To replicate this behavior just create an object that contains a Dictionary<SomeCLRObject, SomeCLRObject> and save it. I attached a sample to the SortedList bug that shows this behavior. |
| Comments |
| Comment by Robert Stam [ 02/Jun/11 ] |
|
This JIRA ticket refers to an older community driver. The official driver supports serializing Dictionaries where the keys are not strings. It serializes them as an array of key/value pairs stored in 2-element arrays. But see the newly created JIRA ticket for a minor improvement to this: |
| Comment by Chris Nicola [ 01/Jun/11 ] |
|
One way this limitation could be worked around is to serialize this as an array of KeyValuePari<T1,T2> objects like so: [{key: { /* some key object */ }, value: { /* some value object */ }]. I believe custom serialization for the .NET driver is flexible enough for someone to implement this, though I could be wrong. |
| Comment by Craig Wilson [ 19/Jun/10 ] |
|
This is unsupportable feature and is most likely impossible to implement. |
| Comment by Craig Wilson [ 19/Jun/10 ] |
|
Understood. This is ultimately going to be a limitation imposed by Json and it will be fairly difficult (if not impossible) to work outside these constraints for an arbitrarily complex key. I don't think the choice of using an IDictionary<,> is the wrong choice however. It is exactly what it is. A hashed set of values based on a key. You are free to implement IDictionaryAdapter to support some custom types of solutions, but ultimately keys will have to be serialized and deserialized as strings. It's as simple as that. I'm going to close this issue as won't resolve. We can reopen it if necessary. |
| Comment by nisbus [ 19/Jun/10 ] |
|
Since Dictionaries in C# don't have this limitation I wonder if mapping them to a JSON dictionary is the correct way to handle this. I have my doubt's about creating an implicit string operator since you would also have to deserialize it back to an object from the string which would be a major headache when using complex objects as keys. I'm guessing that a string in Json has some limitations as to length and so using an IConvertible<string> for large object graphs as key would not work either. Consider this class: class SomeClassUsingDictionary } abstract class DeepAbstractObjectGraphObject : IComparable { public List<AnotherComplexObject> SomeList {get;set;} } I don't see any obvious way to serialize SomeClassUsingDictionary other than converting the MyFunkyDictionary to List<DeepAbstractObjectGraphObject> and List<string> for storage and then deserializing it back to Dictionary. My two cents |
| Comment by Craig Wilson [ 19/Jun/10 ] |
|
Thanks for reporting. This is always going to be an issue and there isn't a lot we can do about it. MongoDb stores everything in Json. The Json spec says that all keys are strings. Therefore, in the driver, we have to serialize both to a string and from a string. If you tried this with an integer as the key, it would work because there is a conversion from int to string and vice versa implicity. So, I'd like to know if creating an implicit string operator on SomeCLRObject would allow this to work. Alternatively, we could always look for IConvertible<string> or something to handle this. Please comment back with your thoughts. |