示例#1
0
        public void TestDoesNotThrowExceptionWhenEverythingIsKosherWithAWriteConcernResult()
        {
            var response = new BsonDocument
            {
                { "n", 1 },
                { "connectionId", 1 },
                { "ok", 1 }
            };

            var writeConcernResult = new WriteConcernResult(response);

            writeConcernResult.ServerInstance = _primary;
            var ex = ExceptionMapper.Map(writeConcernResult);

            Assert.IsNull(ex);
        }
        private CursorBatch <TDocument> ProcessReply(ConnectionId connectionId, ReplyMessage <TDocument> reply)
        {
            if (reply.CursorNotFound)
            {
                throw new MongoCursorNotFoundException(connectionId, _cursorId, _query);
            }

            if (reply.QueryFailure)
            {
                var failureDocument = reply.QueryFailureDocument;
                var errorMessage    = string.Format("GetMore QueryFailure: {0}.", failureDocument);
                throw ExceptionMapper.Map(connectionId, failureDocument) ?? new MongoQueryException(connectionId, errorMessage, _query, failureDocument);
            }

            return(new CursorBatch <TDocument>(reply.CursorId, reply.Documents));
        }
示例#3
0
        public async Task <CursorBatch <TDocument> > ExecuteAsync(IConnection connection, TimeSpan timeout, CancellationToken cancellationToken)
        {
            var slidingTimeout = new SlidingTimeout(timeout);
            var message        = CreateMessage();
            await connection.SendMessageAsync(message, _messageEncoderSettings, slidingTimeout, cancellationToken);

            var reply = await connection.ReceiveMessageAsync <TDocument>(message.RequestId, _serializer, _messageEncoderSettings, slidingTimeout, cancellationToken);

            if (reply.QueryFailure)
            {
                var failureDocument = reply.QueryFailureDocument;
                var errorMessage    = string.Format("GetMore QueryFailure: {0}.", failureDocument);
                throw ExceptionMapper.Map(failureDocument) ?? new MongoQueryException(errorMessage, _query, failureDocument);
            }
            return(new CursorBatch <TDocument>(reply.CursorId, reply.Documents));
        }
        public void TestThrowsWriteConcernExceptionWhenOkButHasLastErrorMessage()
        {
            var response = new BsonDocument
            {
                { "err", "oops" },
                { "code", 20 },
                { "n", 0 },
                { "connectionId", 1 },
                { "ok", 1 }
            };

            var writeConcernResult = new WriteConcernResult(response);
            var ex = ExceptionMapper.Map(writeConcernResult);

            Assert.IsNotNull(ex);
            Assert.IsInstanceOf <WriteConcernException>(ex);
        }
        public void TestThrowsDuplicateKeyExceptionForMongod(int code)
        {
            var response = new BsonDocument
            {
                { "ok", 1 },
                { "err", string.Format("E{0} duplicate key error index: test.foo.$_id_  dup key: {{ : 1.0 }}", code) },
                { "code", code },
                { "n", 0 },
                { "connectionId", 1 }
            };

            var writeConcernResult = new WriteConcernResult(response);
            var ex = ExceptionMapper.Map(writeConcernResult);

            Assert.IsNotNull(ex);
            Assert.IsInstanceOf <MongoDuplicateKeyException>(ex);
        }
示例#6
0
        public void TestThrowsWriteConcernExceptionWhenNotOk()
        {
            var response = new BsonDocument
            {
                { "err", "oops" },
                { "code", 20 },
                { "n", 0 },
                { "connectionId", 1 },
                { "ok", 0 }
            };

            var writeConcernResult = new WriteConcernResult(response);

            writeConcernResult.ServerInstance = _primary;
            var ex = ExceptionMapper.Map(writeConcernResult);

            Assert.IsNotNull(ex);
            Assert.IsInstanceOf <WriteConcernException>(ex);
        }
        private CursorBatch <TDocument> ProcessReply(ReplyMessage <TDocument> reply)
        {
            if (reply.QueryFailure)
            {
                var document = reply.QueryFailureDocument;

                var mappedException = ExceptionMapper.Map(document);
                if (mappedException != null)
                {
                    throw mappedException;
                }

                var err     = document.GetValue("$err", "Unknown error.");
                var message = string.Format("QueryFailure flag was {0} (response was {1}).", err, document.ToJson());
                throw new MongoQueryException(message, _query, document);
            }

            return(new CursorBatch <TDocument>(reply.CursorId, reply.Documents));
        }
示例#8
0
        protected WriteConcernResult ReadWriteConcernResult(MongoConnection connection, SendMessageWithWriteConcernResult sendMessageResult)
        {
            var writeConcernResultSerializer = BsonSerializer.LookupSerializer(typeof(WriteConcernResult));
            var replyMessage = connection.ReceiveMessage <WriteConcernResult>(ReaderSettings, writeConcernResultSerializer, null);

            if (replyMessage.NumberReturned == 0)
            {
                throw new MongoCommandException("Command 'getLastError' failed. No response returned");
            }
            var writeConcernResult = replyMessage.Documents[0];

            writeConcernResult.Command = sendMessageResult.GetLastErrorCommand;

            var mappedException = ExceptionMapper.Map(writeConcernResult);

            if (mappedException != null)
            {
                throw mappedException;
            }

            return(writeConcernResult);
        }
示例#9
0
        /// <summary>
        /// If error results exist in the context, maps each error code to a specific exception
        /// type, then builds and throws a <see cref="MultiStatusException{T}"/>, with specific
        /// exceptions nested within.
        /// </summary>
        /// <typeparam name="T">The type of data entity.</typeparam>
        /// <param name="context">The object of state through the pipeline.</param>
        /// <param name="logger">The logging instance.</param>
        /// <param name="cancellationToken">
        /// A cancellation token that can be used by other objects or threads to receive notice of cancellation.
        /// </param>
        /// <returns>The completed asynchronous task.</returns>
        protected override Task _ProcessAsync <T>(
            PipelineContext <T> context,
            ILogger logger,
            CancellationToken cancellationToken)
        {
            if (context.Results == null || !context.Results.ErrorItems.Any())
            {
                return(Task.CompletedTask);
            }

            var exceptions = new List <ApiException>();

            foreach (ErrorItem <T> errorItem in context.Results.ErrorItems)
            {
                exceptions.Add(ExceptionMapper.Map(errorItem.Code, errorItem.Message, errorItem.Extra));
            }

            throw new MultiStatusException <T>(
                      "One or more items in the batch failed. See inner exception for details.",
                      new AggregateException(exceptions),
                      context.Results);
        }
示例#10
0
        // public methods
        public Exception ToWriteConcernException(ConnectionId connectionId, MongoBulkWriteOperationException bulkWriteException)
        {
            var writeConcernResult = ToWriteConcernResult(bulkWriteException.Result, bulkWriteException);

            var exception = ExceptionMapper.Map(connectionId, writeConcernResult.Response);

            if (exception == null)
            {
                exception = ExceptionMapper.Map(connectionId, writeConcernResult);
            }
            if (exception == null)
            {
                exception = new MongoWriteConcernException(connectionId, bulkWriteException.Message, writeConcernResult);
            }

            var writeConcernException = exception as MongoWriteConcernException;

            if (writeConcernException != null)
            {
                writeConcernException.Data["results"] = new List <WriteConcernResult>(new[] { writeConcernResult });
            }

            return(exception); // usually a WriteConcernException unless ExceptionMapper chose a different type
        }
示例#11
0
        private CursorBatch <TDocument> ProcessReply(ConnectionId connectionId, ReplyMessage <TDocument> reply)
        {
            if (reply.QueryFailure)
            {
                var response = reply.QueryFailureDocument;

                var notPrimaryOrNodeIsRecoveringException = ExceptionMapper.MapNotPrimaryOrNodeIsRecovering(connectionId, response, "$err");
                if (notPrimaryOrNodeIsRecoveringException != null)
                {
                    throw notPrimaryOrNodeIsRecoveringException;
                }

                var mappedException = ExceptionMapper.Map(connectionId, response);
                if (mappedException != null)
                {
                    throw mappedException;
                }

                var message = string.Format("QueryFailure flag was true (response was {0}).", response.ToJson());
                throw new MongoQueryException(connectionId, message, _query, response);
            }

            return(new CursorBatch <TDocument>(reply.CursorId, reply.Documents));
        }
示例#12
0
        // internal methods
        internal void ReadFrom(BsonBuffer buffer, IBsonSerializationOptions serializationOptions)
        {
            if (serializationOptions == null && typeof(TDocument) == typeof(BsonDocument))
            {
                serializationOptions = DocumentSerializationOptions.AllowDuplicateNamesInstance;
            }

            var messageStartPosition = buffer.Position;

            ReadMessageHeaderFrom(buffer);
            _responseFlags  = (ResponseFlags)buffer.ReadInt32();
            _cursorId       = buffer.ReadInt64();
            _startingFrom   = buffer.ReadInt32();
            _numberReturned = buffer.ReadInt32();

            if ((_responseFlags & ResponseFlags.CursorNotFound) != 0)
            {
                throw new MongoQueryException("Cursor not found.");
            }
            if ((_responseFlags & ResponseFlags.QueryFailure) != 0)
            {
                BsonDocument document;
                using (BsonReader bsonReader = new BsonBinaryReader(buffer, false, _readerSettings))
                {
                    document = (BsonDocument)BsonDocumentSerializer.Instance.Deserialize(bsonReader, typeof(BsonDocument), null);
                }

                var mappedException = ExceptionMapper.Map(document);
                if (mappedException != null)
                {
                    throw mappedException;
                }

                var err     = document.GetValue("$err", "Unknown error.");
                var message = string.Format("QueryFailure flag was {0} (response was {1}).", err, document.ToJson());
                throw new MongoQueryException(message, document);
            }

            _documents = new List <TDocument>(_numberReturned);
            for (int i = 0; i < _numberReturned; i++)
            {
                BsonBuffer sliceBuffer;
                if (buffer.ByteBuffer is MultiChunkBuffer)
                {
                    // we can use slightly faster SingleChunkBuffers for all documents that don't span chunk boundaries
                    var position = buffer.Position;
                    var length   = buffer.ReadInt32();
                    var slice    = buffer.ByteBuffer.GetSlice(position, length);
                    buffer.Position = position + length;
                    sliceBuffer     = new BsonBuffer(slice, true);
                }
                else
                {
                    sliceBuffer = new BsonBuffer(buffer.ByteBuffer, false);
                }

                using (var bsonReader = new BsonBinaryReader(sliceBuffer, true, _readerSettings))
                {
                    var document = (TDocument)_serializer.Deserialize(bsonReader, typeof(TDocument), serializationOptions);
                    _documents.Add(document);
                }
            }
        }
        private TCommandResult ProcessReply(ConnectionId connectionId, ReplyMessage <RawBsonDocument> reply)
        {
            if (reply.NumberReturned == 0)
            {
                throw new MongoCommandException(connectionId, "Command returned no documents.", _command);
            }
            if (reply.NumberReturned > 1)
            {
                throw new MongoCommandException(connectionId, "Command returned multiple documents.", _command);
            }
            if (reply.QueryFailure)
            {
                var failureDocument = reply.QueryFailureDocument;
                throw ExceptionMapper.Map(connectionId, failureDocument) ?? new MongoCommandException(connectionId, "Command failed.", _command, failureDocument);
            }

            using (var rawDocument = reply.Documents[0])
            {
                var binaryReaderSettings = new BsonBinaryReaderSettings();
                if (_messageEncoderSettings != null)
                {
                    binaryReaderSettings.Encoding = _messageEncoderSettings.GetOrDefault <UTF8Encoding>(MessageEncoderSettingsName.ReadEncoding, Utf8Encodings.Strict);
#pragma warning disable 618
                    if (BsonDefaults.GuidRepresentationMode == GuidRepresentationMode.V2)
                    {
                        binaryReaderSettings.GuidRepresentation = _messageEncoderSettings.GetOrDefault <GuidRepresentation>(MessageEncoderSettingsName.GuidRepresentation, GuidRepresentation.CSharpLegacy);
                    }
#pragma warning restore 618
                }
                ;

                BsonValue clusterTime;
                if (rawDocument.TryGetValue("$clusterTime", out clusterTime))
                {
                    // note: we are assuming that _session is an instance of ClusterClockAdvancingClusterTime
                    // and that calling _session.AdvanceClusterTime will have the side effect of advancing the cluster's ClusterTime also
                    var materializedClusterTime = ((RawBsonDocument)clusterTime).Materialize(binaryReaderSettings);
                    _session.AdvanceClusterTime(materializedClusterTime);
                }
                BsonValue operationTime;
                if (rawDocument.TryGetValue("operationTime", out operationTime))
                {
                    _session.AdvanceOperationTime(operationTime.AsBsonTimestamp);
                }

                if (!rawDocument.GetValue("ok", false).ToBoolean())
                {
                    var materializedDocument = rawDocument.Materialize(binaryReaderSettings);

                    var commandName = _command.GetElement(0).Name;
                    if (commandName == "$query")
                    {
                        commandName = _command["$query"].AsBsonDocument.GetElement(0).Name;
                    }

                    var notPrimaryOrNodeIsRecoveringException = ExceptionMapper.MapNotPrimaryOrNodeIsRecovering(connectionId, _command, materializedDocument, "errmsg");
                    if (notPrimaryOrNodeIsRecoveringException != null)
                    {
                        throw notPrimaryOrNodeIsRecoveringException;
                    }

                    string    message;
                    BsonValue errmsgBsonValue;
                    if (materializedDocument.TryGetValue("errmsg", out errmsgBsonValue) && errmsgBsonValue.IsString)
                    {
                        var errmsg = errmsgBsonValue.ToString();
                        message = string.Format("Command {0} failed: {1}.", commandName, errmsg);
                    }
                    else
                    {
                        message = string.Format("Command {0} failed.", commandName);
                    }

                    var mappedException = ExceptionMapper.Map(connectionId, materializedDocument);
                    if (mappedException != null)
                    {
                        throw mappedException;
                    }

                    throw new MongoCommandException(connectionId, message, _command, materializedDocument);
                }

                if (rawDocument.Contains("writeConcernError"))
                {
                    var materializedDocument = rawDocument.Materialize(binaryReaderSettings);
                    var writeConcernError    = materializedDocument["writeConcernError"].AsBsonDocument;
                    var message            = writeConcernError.AsBsonDocument.GetValue("errmsg", null)?.AsString;
                    var writeConcernResult = new WriteConcernResult(materializedDocument);
                    throw new MongoWriteConcernException(connectionId, message, writeConcernResult);
                }

                using (var stream = new ByteBufferStream(rawDocument.Slice, ownsBuffer: false))
                {
                    var encoderFactory = new BinaryMessageEncoderFactory(stream, _messageEncoderSettings);
                    var encoder        = (ReplyMessageBinaryEncoder <TCommandResult>)encoderFactory.GetReplyMessageEncoder <TCommandResult>(_resultSerializer);
                    using (var reader = encoder.CreateBinaryReader())
                    {
                        var context = BsonDeserializationContext.CreateRoot(reader);
                        return(_resultSerializer.Deserialize(context));
                    }
                }
            }
        }
 public void ExceptionMapper_MapsServerExceptionsAsExpected()
 {
     Assert.IsInstanceOfType(ExceptionMapper.Map(500), typeof(InternalServerException));
     Assert.IsInstanceOfType(ExceptionMapper.Map(501), typeof(MethodNotImplementedException));
     Assert.IsInstanceOfType(ExceptionMapper.Map(503), typeof(ServiceUnavailableException));
 }
        private TCommandResult ProcessReply(ConnectionId connectionId, ReplyMessage <RawBsonDocument> reply)
        {
            if (reply.NumberReturned == 0)
            {
                throw new MongoCommandException(connectionId, "Command returned no documents.", _command);
            }
            if (reply.NumberReturned > 1)
            {
                throw new MongoCommandException(connectionId, "Command returned multiple documents.", _command);
            }
            if (reply.QueryFailure)
            {
                var failureDocument = reply.QueryFailureDocument;
                throw ExceptionMapper.Map(connectionId, failureDocument) ?? new MongoCommandException(connectionId, "Command failed.", _command, failureDocument);
            }

            using (var rawDocument = reply.Documents[0])
            {
                if (!rawDocument.GetValue("ok", false).ToBoolean())
                {
                    var binaryReaderSettings = new BsonBinaryReaderSettings();
                    if (_messageEncoderSettings != null)
                    {
                        binaryReaderSettings.Encoding           = _messageEncoderSettings.GetOrDefault <UTF8Encoding>(MessageEncoderSettingsName.ReadEncoding, Utf8Encodings.Strict);
                        binaryReaderSettings.GuidRepresentation = _messageEncoderSettings.GetOrDefault <GuidRepresentation>(MessageEncoderSettingsName.GuidRepresentation, GuidRepresentation.CSharpLegacy);
                    }
                    ;
                    var materializedDocument = rawDocument.Materialize(binaryReaderSettings);

                    var commandName = _command.GetElement(0).Name;
                    if (commandName == "$query")
                    {
                        commandName = _command["$query"].AsBsonDocument.GetElement(0).Name;
                    }

                    var notPrimaryOrNodeIsRecoveringException = ExceptionMapper.MapNotPrimaryOrNodeIsRecovering(connectionId, materializedDocument, "errmsg");
                    if (notPrimaryOrNodeIsRecoveringException != null)
                    {
                        throw notPrimaryOrNodeIsRecoveringException;
                    }

                    string    message;
                    BsonValue errmsgBsonValue;
                    if (materializedDocument.TryGetValue("errmsg", out errmsgBsonValue) && errmsgBsonValue.IsString)
                    {
                        var errmsg = errmsgBsonValue.ToString();
                        message = string.Format("Command {0} failed: {1}.", commandName, errmsg);
                    }
                    else
                    {
                        message = string.Format("Command {0} failed.", commandName);
                    }

                    var mappedException = ExceptionMapper.Map(connectionId, materializedDocument);
                    if (mappedException != null)
                    {
                        throw mappedException;
                    }

                    throw new MongoCommandException(connectionId, message, _command, materializedDocument);
                }

                using (var stream = new ByteBufferStream(rawDocument.Slice, ownsBuffer: false))
                {
                    var encoderFactory = new BinaryMessageEncoderFactory(stream, _messageEncoderSettings);
                    var encoder        = (ReplyMessageBinaryEncoder <TCommandResult>)encoderFactory.GetReplyMessageEncoder <TCommandResult>(_resultSerializer);
                    using (var reader = encoder.CreateBinaryReader())
                    {
                        var context = BsonDeserializationContext.CreateRoot(reader);
                        return(_resultSerializer.Deserialize(context));
                    }
                }
            }
        }
        private TCommandResult ProcessResponse(ConnectionId connectionId, CommandMessage responseMessage)
        {
            using (new CommandMessageDisposer(responseMessage))
            {
                var rawDocument = responseMessage.Sections.OfType <Type0CommandMessageSection <RawBsonDocument> >().Single().Document;

                var binaryReaderSettings = new BsonBinaryReaderSettings();
                if (_messageEncoderSettings != null)
                {
                    binaryReaderSettings.Encoding           = _messageEncoderSettings.GetOrDefault <UTF8Encoding>(MessageEncoderSettingsName.ReadEncoding, Utf8Encodings.Strict);
                    binaryReaderSettings.GuidRepresentation = _messageEncoderSettings.GetOrDefault <GuidRepresentation>(MessageEncoderSettingsName.GuidRepresentation, GuidRepresentation.CSharpLegacy);
                }
                ;

                BsonValue clusterTime;
                if (rawDocument.TryGetValue("$clusterTime", out clusterTime))
                {
                    // note: we are assuming that _session is an instance of ClusterClockAdvancingClusterTime
                    // and that calling _session.AdvanceClusterTime will have the side effect of advancing the cluster's ClusterTime also
                    var materializedClusterTime = ((RawBsonDocument)clusterTime).Materialize(binaryReaderSettings);
                    _session.AdvanceClusterTime(materializedClusterTime);
                }

                BsonValue operationTime;
                if (rawDocument.TryGetValue("operationTime", out operationTime))
                {
                    _session.AdvanceOperationTime(operationTime.AsBsonTimestamp);
                }

                if (!rawDocument.GetValue("ok", false).ToBoolean())
                {
                    var materializedDocument = rawDocument.Materialize(binaryReaderSettings);

                    var commandName = _command.GetElement(0).Name;
                    if (commandName == "$query")
                    {
                        commandName = _command["$query"].AsBsonDocument.GetElement(0).Name;
                    }

                    var notPrimaryOrNodeIsRecoveringException = ExceptionMapper.MapNotPrimaryOrNodeIsRecovering(connectionId, materializedDocument, "errmsg");
                    if (notPrimaryOrNodeIsRecoveringException != null)
                    {
                        throw notPrimaryOrNodeIsRecoveringException;
                    }

                    var mappedException = ExceptionMapper.Map(connectionId, materializedDocument);
                    if (mappedException != null)
                    {
                        throw mappedException;
                    }

                    string    message;
                    BsonValue errmsgBsonValue;
                    if (materializedDocument.TryGetValue("errmsg", out errmsgBsonValue) && errmsgBsonValue.IsString)
                    {
                        var errmsg = errmsgBsonValue.ToString();
                        message = string.Format("Command {0} failed: {1}.", commandName, errmsg);
                    }
                    else
                    {
                        message = string.Format("Command {0} failed.", commandName);
                    }

                    throw new MongoCommandException(connectionId, message, _command, materializedDocument);
                }

                using (var stream = new ByteBufferStream(rawDocument.Slice, ownsBuffer: false))
                {
                    using (var reader = new BsonBinaryReader(stream, binaryReaderSettings))
                    {
                        var context = BsonDeserializationContext.CreateRoot(reader);
                        return(_resultSerializer.Deserialize(context));
                    }
                }
            }
        }
 public override void When()
 {
     ActualResult = ExceptionMapper.Map(Input);
 }
 public void ExceptionMapper_MapsUnmappedExceptionsAsExpected()
 {
     Assert.IsInstanceOfType(ExceptionMapper.Map(999), typeof(UnmappedApiException));
 }
        private TCommandResult ProcessResponse(ConnectionId connectionId, CommandMessage responseMessage)
        {
            using (new CommandMessageDisposer(responseMessage))
            {
                var rawDocument = responseMessage.Sections.OfType <Type0CommandMessageSection <RawBsonDocument> >().Single().Document;

                var binaryReaderSettings = new BsonBinaryReaderSettings();
                if (_messageEncoderSettings != null)
                {
                    binaryReaderSettings.Encoding = _messageEncoderSettings.GetOrDefault <UTF8Encoding>(MessageEncoderSettingsName.ReadEncoding, Utf8Encodings.Strict);
#pragma warning disable 618
                    if (BsonDefaults.GuidRepresentationMode == GuidRepresentationMode.V2)
                    {
                        binaryReaderSettings.GuidRepresentation = _messageEncoderSettings.GetOrDefault <GuidRepresentation>(MessageEncoderSettingsName.GuidRepresentation, GuidRepresentation.CSharpLegacy);
                    }
#pragma warning restore 618
                }
                ;

                BsonValue clusterTime;
                if (rawDocument.TryGetValue("$clusterTime", out clusterTime))
                {
                    // note: we are assuming that _session is an instance of ClusterClockAdvancingClusterTime
                    // and that calling _session.AdvanceClusterTime will have the side effect of advancing the cluster's ClusterTime also
                    var materializedClusterTime = ((RawBsonDocument)clusterTime).Materialize(binaryReaderSettings);
                    _session.AdvanceClusterTime(materializedClusterTime);
                }

                BsonValue operationTime;
                if (rawDocument.TryGetValue("operationTime", out operationTime))
                {
                    _session.AdvanceOperationTime(operationTime.AsBsonTimestamp);
                }

                if (rawDocument.GetValue("ok", false).ToBoolean())
                {
                    if (rawDocument.TryGetValue("recoveryToken", out var rawRecoveryToken))
                    {
                        var recoveryToken = ((RawBsonDocument)rawRecoveryToken).Materialize(binaryReaderSettings);
                        _session.CurrentTransaction.RecoveryToken = recoveryToken;
                    }
                }
                else
                {
                    var materializedDocument = rawDocument.Materialize(binaryReaderSettings);

                    var commandName = _command.GetElement(0).Name;
                    if (commandName == "$query")
                    {
                        commandName = _command["$query"].AsBsonDocument.GetElement(0).Name;
                    }

                    var notPrimaryOrNodeIsRecoveringException = ExceptionMapper.MapNotPrimaryOrNodeIsRecovering(connectionId, _command, materializedDocument, "errmsg");
                    if (notPrimaryOrNodeIsRecoveringException != null)
                    {
                        throw notPrimaryOrNodeIsRecoveringException;
                    }

                    var mappedException = ExceptionMapper.Map(connectionId, materializedDocument);
                    if (mappedException != null)
                    {
                        throw mappedException;
                    }

                    string    message;
                    BsonValue errmsgBsonValue;
                    if (materializedDocument.TryGetValue("errmsg", out errmsgBsonValue) && errmsgBsonValue.IsString)
                    {
                        var errmsg = errmsgBsonValue.ToString();
                        message = string.Format("Command {0} failed: {1}.", commandName, errmsg);
                    }
                    else
                    {
                        message = string.Format("Command {0} failed.", commandName);
                    }

                    var exception = new MongoCommandException(connectionId, message, _command, materializedDocument);

                    // https://jira.mongodb.org/browse/CSHARP-2678
                    if (IsRetryableWriteExceptionAndDeploymentDoesNotSupportRetryableWrites(exception))
                    {
                        throw WrapNotSupportedRetryableWriteException(exception);
                    }
                    else
                    {
                        throw exception;
                    }
                }

                if (rawDocument.Contains("writeConcernError"))
                {
                    var materializedDocument = rawDocument.Materialize(binaryReaderSettings);
                    var writeConcernError    = materializedDocument["writeConcernError"].AsBsonDocument;
                    var message            = writeConcernError.AsBsonDocument.GetValue("errmsg", null)?.AsString;
                    var writeConcernResult = new WriteConcernResult(materializedDocument);
                    throw new MongoWriteConcernException(connectionId, message, writeConcernResult);
                }

                using (var stream = new ByteBufferStream(rawDocument.Slice, ownsBuffer: false))
                {
                    using (var reader = new BsonBinaryReader(stream, binaryReaderSettings))
                    {
                        var context = BsonDeserializationContext.CreateRoot(reader);
                        return(_resultSerializer.Deserialize(context));
                    }
                }
            }
        }