When I wrote code to grab a nested property, it fails when the entire path doesn't exist - which is fair enough
bsonDoc["Meeting"]["Session"]["Time"]
I can't see any way to protect against this, writing
bsonDoc.Contains("Meeting.Session.Time")
returns false
even when it exists
Writing bsonDoc.Contains("Time")
also returns fails, even when it does exist, so it can't even check the field property at all, if it's nested... ?
The documentation and even the code contains no clue how to do what I need. Not sure it's possible.
Is there a way to write a guard clause for nested bson document properties - ie does the BsonDocument class have a nested key checking mechanism?
I don't think there is any method from BsonDocument
that supports getting element/value with the nested property.
But you can implement the logic/extension method to deal with:
Concept:
Split key by '.'.
First-level search.
2.1 First chainKey
will search from BsonDocument
via TryGetValue
.
2.2 If the key has existed, @value
(BsonValue
) will contain value (This is needed while querying for nested levels).
2.3 If the key doesn't exist, break the loop logic.
Second-level or further level search
3.1 Concept is the same with 2, just will search from BsonValue
(as stated in 2.2).
public static class BsonDocumentExtensions
{
public static bool TryGetChainedValue(this BsonDocument doc, string key, out BsonValue @value)
{
@value = default;
// Get key, value from passed BsonDocument for first time, then refer to BsonValue to get key, value for nested property
bool first = true;
try
{
if (String.IsNullOrWhiteSpace(key))
return false;
string[] chainedKeys = key.Split(".").ToArray();
bool hasKey = false;
foreach (var chainKey in chainedKeys)
{
if (first)
{
hasKey = doc.TryGetValue(chainKey, out @value);
first = false;
}
else
{
hasKey = (@value.ToBsonDocument()).TryGetValue(chainKey, out @value);
}
// Throw exception if key not existed.
if (!hasKey)
throw new Exception();
}
return true;
}
catch
{
@value = default;
return false;
}
}
}
The concept above is same as multiple if logic as below:
if (doc.TryGetValue("Meeting", out BsonValue meetingValue))
{
if ((meetingValue.ToBsonDocument()).TryGetValue("Session", out BsonValue sessionValue))
{
if ((sessionValue.ToBsonDocument()).TryGetValue("Time", out BsonValue timeValue))
{
Console.WriteLine(timeValue);
}
}
}