2

I am attempting to create an array of array of dictionaries in ASP.NET Core using MongoDB. In the end, the data should retain this model for all uses:

Model

{
    "ContextName": "Base rates",
    "Indexes": [
        {
            "IndexName": "S&P",
            "IndexValues" : [
                {
                    "Date": "2019-01-01",
                    "Value": "2600.98"
                },
                {
                    "Date": "2019-01-02",
                    "Value": "2605.98"
                }              
            ]
        }
    ]
}

Currently, I have my first layer defined below encompassing the ContextName and Indexes:

Context.cs

public class Context
    {
        [BsonId]
        [BsonRepresentation(MongoDB.Bson.BsonType.ObjectId)]
        public string Id { get; set; }
        [BsonElement("ContextName")]
        public string ContextName { get; set; }
        [BsonElement("Indexes")]
        public ICollection<Index> Indexes { get; set; }
    }

With Index having the following structure:

Index.cs

public class Index
    {
        [BsonElement("IndexName")]
        public string IndexName { get; set; }
        [BsonElement("IndexValues")]
        [BsonDictionaryOptions(DictionaryRepresentation.ArrayOfDocuments)]
        public Dictionary<DateTime, double> IndexValues { get; set; }
    }

Running this code I am met with a Format Exception stating

An error occurred while deserializing the IndexValues property of class Database.Index: Invalid element: 'Date'.'

My first thought is that it is an issue with the key being of type Date and not of string within the database itself, however I have read here towards the bottom that the official driver supports this actually.

I went a bit further to try and set some custom { get; set; } to bring in the key as a string but am being met with the same error in the end.

public Dictionary<DateTime, double> IndexValues
        {
            get
            {
                Dictionary<DateTime, double> _indexValues = new Dictionary<DateTime, double>();
                foreach (var indexValue in IndexValues)
                {
                    _indexValues.Add(indexValue.Key, indexValue.Value);
                }
                return _indexValues;
            }
            set { IndexValues = IndexValues; } // Unsure about here as well
        }

I am unsure what to be looking at for this case, and am looking for some pointers to figure this out. Thanks in advance.

Update

Formatting the dictionary in an external method allows for the correct format, however also inserts one extra field as it is used in gathering all the required information.

public Dictionary<DateTime, double> IndexValuesDictionary
        {
            get { return SetDictionary(); }
            set { SetDictionary(); }
        }

        private Dictionary<DateTime, double> SetDictionary()
        {
            if (_indexValues == null)
            {
                _indexValues = new Dictionary<DateTime, double>();
                foreach (var indexValue in IndexValues)
                {
                    _indexValues.Add(indexValue.Date, indexValue.Value);
                }
            }
            return _indexValues;
        }
{
        "id": "5c93c1123369220b685719b3",
        "contextName": "Base rates",
        "indexes": [
            {
                "indexName": "S&P",
                "indexValues": [
                    {
                        "date": "2019-01-01T00:00:00Z",
                        "value": 2600.98
                    },
                    {
                        "date": "2019-01-02T00:00:00Z",
                        "value": 2605.98
                    }
                ],
                "indexValuesDictionary": { // This should not be included
                    "2019-01-01T00:00:00Z": 2600.98,
                    "2019-01-02T00:00:00Z": 2605.98
                }
            }
        ]
    }

Is this the only viable option for this output?

1 Answer 1

1

After taking a step back and looking at the data structure, I was able to get this working by removing the array nesting and working solely with document nesting (unfortunate but simplifies the schema). The updated database structure is:

[
    {
        "ContextName": "Base rates",
        "Description": "Base rates description",
        "Indexes": {
            "SPX": {
                "2019-01-01T00:00:00Z": 2600.98
            },
            "NDX": {
                "2019-01-01T00:00:00Z": 6600.98
            }
        }
    }
]

Leaving the class structures updated as:

Context.cs

public class Context
    {
        [BsonId]
        [BsonRepresentation(BsonType.ObjectId)]
        public string Id { get; set; }
        [BsonElement("ContextName")]
        public string ContextName { get; set; }
        [BsonElement("Description")]
        public string Description { get; set; }
        [BsonElement("Indexes")]
        [BsonDictionaryOptions(DictionaryRepresentation.Document)]
        public Index Indexes { get; set; }
    }

Index.cs

public class Index : Dictionary<string, Dictionary<DateTime, double>> { }

I also changed the serializer to treat DateTime as a string instead, and so included this in the program startup:

BsonSerializer.RegisterSerializer(new DateTimeSerializer(DateTimeKind.Local, BsonType.String));

These changes allow the structure to be formatted correctly.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.