diff --git a/src/MongoDB.Bson/ObjectModel/BsonDocument.cs b/src/MongoDB.Bson/ObjectModel/BsonDocument.cs
index 0b57ad3aa01..ae45c85f6a1 100644
--- a/src/MongoDB.Bson/ObjectModel/BsonDocument.cs
+++ b/src/MongoDB.Bson/ObjectModel/BsonDocument.cs
@@ -68,6 +68,22 @@ public BsonDocument(BsonElement element)
Add(element);
}
+ ///
+ /// Initializes a new instance of the BsonDocument by coping elements from another BsonDocument.
+ ///
+ /// The document whose elements will be copied
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
+ public BsonDocument(BsonDocument document)
+ {
+ if (document == null)
+ {
+ throw new ArgumentNullException(nameof(document));
+ }
+
+ _allowDuplicateNames = document.AllowDuplicateNames;
+ AddRange(document);
+ }
+
///
/// Initializes a new instance of the BsonDocument class and adds new elements from a dictionary of key/value pairs.
///
@@ -733,7 +749,7 @@ public virtual void Clear()
/// A shallow clone of the document.
public override BsonValue Clone()
{
- BsonDocument clone = new BsonDocument();
+ BsonDocument clone = new BsonDocument() { AllowDuplicateNames = AllowDuplicateNames };
foreach (BsonElement element in _elements)
{
clone.Add(element.Clone());
@@ -745,7 +761,7 @@ public override BsonValue Clone()
/// Compares this document to another document.
///
/// The other document.
- /// A 32-bit signed integer that indicates whether this document is less than, equal to, or greather than the other.
+ /// A 32-bit signed integer that indicates whether this document is less than, equal to, or greater than the other.
public virtual int CompareTo(BsonDocument rhs)
{
if (rhs == null) { return 1; }
@@ -776,7 +792,7 @@ public virtual int CompareTo(BsonDocument rhs)
/// Compares the BsonDocument to another BsonValue.
///
/// The other BsonValue.
- /// A 32-bit signed integer that indicates whether this BsonDocument is less than, equal to, or greather than the other BsonValue.
+ /// A 32-bit signed integer that indicates whether this BsonDocument is less than, equal to, or greater than the other BsonValue.
public override int CompareTo(BsonValue other)
{
if (other == null) { return 1; }
@@ -818,7 +834,7 @@ public virtual bool ContainsValue(BsonValue value)
/// A deep clone of the document.
public override BsonValue DeepClone()
{
- BsonDocument clone = new BsonDocument();
+ BsonDocument clone = new BsonDocument() { AllowDuplicateNames = AllowDuplicateNames };
foreach (BsonElement element in _elements)
{
clone.Add(element.DeepClone());
diff --git a/tests/MongoDB.Bson.Tests/ObjectModel/BsonDocumentTests.cs b/tests/MongoDB.Bson.Tests/ObjectModel/BsonDocumentTests.cs
index 9489c93a7e6..bf73ded3e68 100644
--- a/tests/MongoDB.Bson.Tests/ObjectModel/BsonDocumentTests.cs
+++ b/tests/MongoDB.Bson.Tests/ObjectModel/BsonDocumentTests.cs
@@ -137,6 +137,21 @@ public void TestClone()
var clone = (BsonDocument)document.Clone();
Assert.Equal(clone, document);
Assert.Same(clone["d"], document["d"]);
+ Assert.False(clone.AllowDuplicateNames);
+ }
+
+ [Fact]
+ public void TestClone_with_duplicate_elements()
+ {
+ var document = new BsonDocument(allowDuplicateNames: true)
+ {
+ { "d", new BsonDocument("x", 1) },
+ { "d", new BsonDocument("x", 2) },
+ };
+
+ var clone = (BsonDocument)document.Clone();
+ clone.Should().Be(document);
+ clone.AllowDuplicateNames.Should().BeTrue();
}
[Fact]
@@ -153,6 +168,7 @@ public void TestConstructorElement()
{
var element = new BsonElement("x", 1);
var document = new BsonDocument(element);
+ Assert.False(document.AllowDuplicateNames);
Assert.Equal(1, document.ElementCount);
Assert.Equal(1, document["x"].AsInt32);
Assert.Equal(true, document.Contains("x"));
@@ -168,6 +184,7 @@ public void TestConstructorElements()
new BsonElement("y", 2)
};
var document = new BsonDocument((IEnumerable)elements);
+ Assert.False(document.AllowDuplicateNames);
Assert.Equal(2, document.ElementCount);
Assert.Equal(1, document["x"].AsInt32);
Assert.Equal(2, document["y"].AsInt32);
@@ -184,6 +201,7 @@ public void TestConstructorElementsDocument()
{
var originalDocument = new BsonDocument { { "x", 1 }, { "y", 2 } };
var document = new BsonDocument(originalDocument);
+ Assert.False(document.AllowDuplicateNames);
Assert.Equal(2, document.ElementCount);
Assert.Equal(1, document["x"].AsInt32);
Assert.Equal(2, document["y"].AsInt32);
@@ -195,6 +213,20 @@ public void TestConstructorElementsDocument()
Assert.Same(originalDocument.GetElement("y").Value, document.GetElement("y").Value);
}
+ [Fact]
+ public void TestConstructorElementsDocumentDuplicateNames()
+ {
+ var documentA = new BsonDocument(allowDuplicateNames: true)
+ {
+ { "x", 1 },
+ { "x", 2 },
+ };
+ var documentB = new BsonDocument(documentA);
+
+ documentB.AllowDuplicateNames.Should().BeTrue();
+ documentB.Elements.ShouldAllBeEquivalentTo(documentA.Elements);
+ }
+
[Fact]
public void TestConstructorElementsParams()
{
@@ -203,6 +235,8 @@ public void TestConstructorElementsParams()
#pragma warning disable 618
var document = new BsonDocument(element1, element2);
#pragma warning restore
+ Assert.False(document.AllowDuplicateNames);
+ Assert.Equal(2, document.ElementCount);
Assert.Equal(2, document.ElementCount);
Assert.Equal(1, document["x"].AsInt32);
Assert.Equal(2, document["y"].AsInt32);
@@ -219,6 +253,7 @@ public void TestConstructorDictionaryGeneric()
{
var dictionary = new Dictionary { { "x", 1 } };
var document = new BsonDocument(dictionary);
+ Assert.False(document.AllowDuplicateNames);
Assert.Equal(1, document.ElementCount);
Assert.Equal(1, document["x"].AsInt32);
Assert.Equal(true, document.Contains("x"));
@@ -233,6 +268,7 @@ public void TestConstructorDictionaryGenericWithKeys()
#pragma warning disable 618
var document = new BsonDocument(dictionary, keys);
#pragma warning restore
+ Assert.False(document.AllowDuplicateNames);
Assert.Equal(1, document.ElementCount);
Assert.Equal(1, document["x"].AsInt32);
Assert.Equal(true, document.Contains("x"));
@@ -244,6 +280,7 @@ public void TestConstructorIDictionary()
{
var hashtable = (IDictionary)new Hashtable { { "x", 1 } };
var document = new BsonDocument(hashtable);
+ Assert.False(document.AllowDuplicateNames);
Assert.Equal(1, document.ElementCount);
Assert.Equal(1, document["x"].AsInt32);
Assert.Equal(true, document.Contains("x"));
@@ -255,6 +292,7 @@ public void TestConstructorIDictionaryGeneric()
{
var dictionary = (IDictionary)new Dictionary { { "x", 1 } };
var document = new BsonDocument(dictionary);
+ Assert.False(document.AllowDuplicateNames);
Assert.Equal(1, document.ElementCount);
Assert.Equal(1, document["x"].AsInt32);
Assert.Equal(true, document.Contains("x"));
@@ -269,6 +307,7 @@ public void TestConstructorIDictionaryGenericWithKeys()
#pragma warning disable 618
var document = new BsonDocument(dictionary, keys);
#pragma warning restore
+ Assert.False(document.AllowDuplicateNames);
Assert.Equal(1, document.ElementCount);
Assert.Equal(1, document["x"].AsInt32);
Assert.Equal(true, document.Contains("x"));
@@ -283,6 +322,7 @@ public void TestConstructorIDictionaryWithKeys()
#pragma warning disable 618
var document = new BsonDocument(hashtable, keys);
#pragma warning restore
+ Assert.False(document.AllowDuplicateNames);
Assert.Equal(1, document.ElementCount);
Assert.Equal(1, document["x"].AsInt32);
Assert.Equal(true, document.Contains("x"));
@@ -293,6 +333,7 @@ public void TestConstructorIDictionaryWithKeys()
public void TestConstructorNameValue()
{
var document = new BsonDocument("x", 1);
+ Assert.False(document.AllowDuplicateNames);
Assert.Equal(1, document.ElementCount);
Assert.Equal(1, document["x"].AsInt32);
Assert.Equal(true, document.Contains("x"));
@@ -374,6 +415,25 @@ public void TestDeepClone()
var clone = (BsonDocument)document.DeepClone();
Assert.Equal(clone, document);
Assert.NotSame(clone["d"], document["d"]);
+ Assert.False(((BsonDocument)document["d"]).AllowDuplicateNames);
+ }
+
+ [Fact]
+ public void TestDeepClone_with_duplicate_elements()
+ {
+ var documentWithDuplicateElements = new BsonDocument(allowDuplicateNames: true)
+ {
+ { "x", 1 },
+ { "x", 2 }
+ };
+
+ var document = new BsonDocument("d", documentWithDuplicateElements);
+ var clone = (BsonDocument)document.DeepClone();
+ var clonedNestedDocument = (BsonDocument)clone["d"];
+
+ clonedNestedDocument.Should().NotBeSameAs((BsonDocument)document["d"]);
+ clonedNestedDocument.Elements.ShouldAllBeEquivalentTo(documentWithDuplicateElements.Elements);
+ clonedNestedDocument.AllowDuplicateNames.Should().BeTrue();
}
[Fact]