private Type0CommandMessageSection <BsonDocument> CreateType0Section(ConnectionDescription connectionDescription)
        {
            var extraElements = new List <BsonElement>();

            AddIfNotAlreadyAdded("$db", _databaseNamespace.DatabaseName);

            if (connectionDescription?.IsMasterResult.ServerType != ServerType.Standalone &&
                _readPreference != null &&
                _readPreference != ReadPreference.Primary)
            {
                var readPreferenceDocument = QueryHelper.CreateReadPreferenceDocument(_readPreference);
                AddIfNotAlreadyAdded("$readPreference", readPreferenceDocument);
            }

            if (_session.Id != null)
            {
                if (IsSessionAcknowledged())
                {
                    AddIfNotAlreadyAdded("lsid", _session.Id);
                }
                else
                {
                    if (_session.IsImplicit)
                    {
                        // do not set sessionId if session is implicit and write is unacknowledged
                    }
                    else
                    {
                        throw new InvalidOperationException("Explicit session must not be used with unacknowledged writes.");
                    }
                }
            }


            var snapshotReadConcernDocument = ReadConcernHelper.GetReadConcernForSnapshotSesssion(_session, connectionDescription);

            if (snapshotReadConcernDocument != null)
            {
                extraElements.Add(new BsonElement("readConcern", snapshotReadConcernDocument));
            }

            if (_session.ClusterTime != null)
            {
                AddIfNotAlreadyAdded("$clusterTime", _session.ClusterTime);
            }
#pragma warning disable 618
            Action <BsonWriterSettings> writerSettingsConfigurator = null;
            if (BsonDefaults.GuidRepresentationMode == GuidRepresentationMode.V2)
            {
                writerSettingsConfigurator = s => s.GuidRepresentation = GuidRepresentation.Unspecified;
            }
#pragma warning restore 618

            _session.AboutToSendCommand();
            if (_session.IsInTransaction)
            {
                var transaction = _session.CurrentTransaction;
                AddIfNotAlreadyAdded("txnNumber", transaction.TransactionNumber);
                if (transaction.State == CoreTransactionState.Starting)
                {
                    AddIfNotAlreadyAdded("startTransaction", true);
                    var readConcern = ReadConcernHelper.GetReadConcernForFirstCommandInTransaction(_session, connectionDescription);
                    if (readConcern != null)
                    {
                        AddIfNotAlreadyAdded("readConcern", readConcern);
                    }
                }
                AddIfNotAlreadyAdded("autocommit", false);
            }
            if (_serverApi != null)
            {
                AddIfNotAlreadyAdded("apiVersion", _serverApi.Version.ToString());
                if (_serverApi.Strict.HasValue)
                {
                    AddIfNotAlreadyAdded("apiStrict", _serverApi.Strict.Value);
                }
                if (_serverApi.DeprecationErrors.HasValue)
                {
                    AddIfNotAlreadyAdded("apiDeprecationErrors", _serverApi.DeprecationErrors.Value);
                }
            }

            var elementAppendingSerializer = new ElementAppendingSerializer <BsonDocument>(BsonDocumentSerializer.Instance, extraElements, writerSettingsConfigurator);
            return(new Type0CommandMessageSection <BsonDocument>(_command, elementAppendingSerializer));

            void AddIfNotAlreadyAdded(string key, BsonValue value)
            {
                if (!_command.Contains(key))
                {
                    extraElements.Add(new BsonElement(key, value));
                }
            }

            bool IsSessionAcknowledged()
            {
                if (_command.TryGetValue("writeConcern", out var writeConcernDocument))
                {
                    var writeConcern = WriteConcern.FromBsonDocument(writeConcernDocument.AsBsonDocument);
                    return(writeConcern.IsAcknowledged);
                }
                else
                {
                    return(true);
                }
            }
        }
Example #2
0
        public static List <BsonElement> _elements <TDocument>(this ElementAppendingSerializer <TDocument> instance)
        {
            var fieldInfo = typeof(ElementAppendingSerializer <TDocument>).GetField("_elements", BindingFlags.NonPublic | BindingFlags.Instance);

            return((List <BsonElement>)fieldInfo.GetValue(instance));
        }
Example #3
0
        private BsonDocument WrapCommandForQueryMessage(BsonDocument command, ConnectionDescription connectionDescription, out bool messageContainsSessionId, out bool secondaryOk)
        {
            messageContainsSessionId = false;
            var extraElements = new List <BsonElement>();

            if (_session.Id != null)
            {
                var areSessionsSupported = connectionDescription.IsMasterResult.LogicalSessionTimeout.HasValue;
                if (areSessionsSupported)
                {
                    var lsid = new BsonElement("lsid", _session.Id);
                    extraElements.Add(lsid);
                    messageContainsSessionId = true;
                }
                else
                {
                    if (!_session.IsImplicit)
                    {
                        throw new MongoClientException("Sessions are not supported.");
                    }
                }
            }
            if (_serverApi != null)
            {
                extraElements.Add(new BsonElement("apiVersion", _serverApi.Version.ToString()));
                if (_serverApi.Strict.HasValue)
                {
                    extraElements.Add(new BsonElement("apiStrict", _serverApi.Strict.Value));
                }
                if (_serverApi.DeprecationErrors.HasValue)
                {
                    extraElements.Add(new BsonElement("apiDeprecationErrors", _serverApi.DeprecationErrors.Value));
                }
            }
            if (_session.ClusterTime != null)
            {
                var clusterTime = new BsonElement("$clusterTime", _session.ClusterTime);
                extraElements.Add(clusterTime);
            }
#pragma warning disable 618
            Action <BsonWriterSettings> writerSettingsConfigurator = null;
            if (BsonDefaults.GuidRepresentationMode == GuidRepresentationMode.V2)
            {
                writerSettingsConfigurator = s => s.GuidRepresentation = GuidRepresentation.Unspecified;
            }
#pragma warning restore 618
            var appendExtraElementsSerializer = new ElementAppendingSerializer <BsonDocument>(BsonDocumentSerializer.Instance, extraElements, writerSettingsConfigurator);
            var commandWithExtraElements      = new BsonDocumentWrapper(command, appendExtraElementsSerializer);

            var serverType             = connectionDescription != null ? connectionDescription.IsMasterResult.ServerType : ServerType.Unknown;
            var readPreferenceDocument = QueryHelper.CreateReadPreferenceDocument(serverType, _readPreference, out secondaryOk);

            var wrappedCommand = new BsonDocument
            {
                { "$query", commandWithExtraElements },
                { "$readPreference", readPreferenceDocument, readPreferenceDocument != null }
            };
            if (_additionalOptions != null)
            {
                wrappedCommand.Merge(_additionalOptions, overwriteExistingElements: false);
            }

            if (wrappedCommand.ElementCount == 1)
            {
                return(wrappedCommand["$query"].AsBsonDocument);
            }
            else
            {
                return(wrappedCommand);
            }
        }