I'm upgrading an existing project from the 1.10.0 Mongo Driver to 2.2.4 and encountered some unexpected behavior in a class that inherits from MongoDB.Bson.BsonDocument
. The original developers extended BsonDocument
with a class called BsonDocumentWithNulls
whose entire purpose is to convert null
to BsonNull.Value
.
In unit tests Assert.AreEqual(new BsonDocument("foo", "bar"), new BsonDocumentWithNulls("foo", "baz"));
fails as it should but the error message doesn't recognize the values in the BsonDocumentWithNulls object. Specifically the error message is Assert.AreEqual failed. Expected:<{ "foo" : "bar" }>. Actual:<[{ }]>.
I know this has something to do with ToString but I don't know how to fix it.
This is the implementation of BsonDocumentWithNulls which works with 1.10.0 of the Mongo driver, but not version 2.2.4.
public sealed class BsonDocumentWithNulls : BsonDocument
{
public BsonDocumentWithNulls()
{ }
public BsonDocumentWithNulls(string key, BsonValue value)
{
if (value == null)
Add(key, BsonNull.Value);
else
Add(key, value);
}
public BsonDocumentWithNulls(IDictionary<string, object> dictionary)
{
foreach (var keyValue in dictionary)
{
if (keyValue.Value == null)
Add(keyValue.Key, BsonNull.Value);
else
Add(keyValue.Key, BsonValue.Create(keyValue.Value));
}
}
}
To add to the confusion I can make the following Assertions in Unit Tests and everything works, which tells me the values are actually being stored in memory.
BsonDocument expected = new BsonDocument("foo", "bar");
BsonDocumentWithNulls actual = new BsonDocumentWithNulls("foo", "bar");
Assert.AreEqual(expected["foo"], actual["foo"]);
Assert.AreEqual(expected.GetElement("foo"), actual.GetElement("foo"));
Assert.AreEqual(expected, actual);
//And just for sanity
Assert.AreEqual("bar", actual["foo"]);
To try and fix the problem I've tried overriding ToString with various implementations.
public override string ToString()
{
return base.ToString();
}
public override string ToString()
{
BsonDocument doc = this.AsBsonDocument;
return doc.ToString();
}
And one of my more naive/creative attempts, but I'll let you be the judge on if its creative or naive.
public override string ToString()
{
string retVal = string.Empty;
foreach(var val in this.Elements)
{
retVal += string.Format("{2}, \"{0}\" : \"{1}\" {3}", val.Name, val.Value, "{", "}");
}
return retVal;
}