// public methods public IEnumerable<WriteConcernResult> Execute(MongoConnection connection) { var serverInstance = connection.ServerInstance; if (serverInstance.Supports(FeatureId.WriteCommands) && _args.WriteConcern.Enabled) { var emulator = new InsertOpcodeOperationEmulator(_args); return emulator.Execute(connection); } var results = WriteConcern.Enabled ? new List<WriteConcernResult>() : null; var finalException = (Exception)null; var requests = _args.Requests.Cast<InsertRequest>(); if (_args.AssignId != null) { requests = requests.Select(r => { _args.AssignId(r); return r; }); } using (var enumerator = requests.GetEnumerator()) { var maxBatchCount = _args.MaxBatchCount; // OP_INSERT is not limited by the MaxBatchCount reported by the server var maxBatchLength = Math.Min(_args.MaxBatchLength, connection.ServerInstance.MaxMessageLength); var maxDocumentSize = connection.ServerInstance.MaxDocumentSize; Batch<InsertRequest> nextBatch = new FirstBatch<InsertRequest>(enumerator); while (nextBatch != null) { // release buffer as soon as possible BatchProgress<InsertRequest> batchProgress; SendMessageWithWriteConcernResult sendBatchResult; using (var buffer = new BsonBuffer(new MultiChunkBuffer(BsonChunkPool.Default), true)) { var flags = _continueOnError ? InsertFlags.ContinueOnError : InsertFlags.None; var message = new MongoInsertMessage( _args.WriterSettings, _args.DatabaseName + "." + _args.CollectionName, _args.CheckElementNames, flags, maxBatchCount, maxBatchLength, maxDocumentSize, nextBatch); message.WriteTo(buffer); // consumes as much of nextBatch as fits in one message batchProgress = message.BatchProgress; sendBatchResult = SendBatch(connection, buffer, message.RequestId, batchProgress.IsLast); } // note: getLastError is sent even when WriteConcern is not enabled if ContinueOnError is false if (sendBatchResult.GetLastErrorRequestId.HasValue) { WriteConcernResult writeConcernResult; try { writeConcernResult = ReadWriteConcernResult(connection, sendBatchResult); } catch (WriteConcernException ex) { writeConcernResult = ex.WriteConcernResult; if (_continueOnError) { finalException = ex; } else if (WriteConcern.Enabled) { results.Add(writeConcernResult); ex.Data["results"] = results; throw; } else { return null; } } if (results != null) { results.Add(writeConcernResult); } } nextBatch = batchProgress.NextBatch; } } if (WriteConcern.Enabled && finalException != null) { finalException.Data["results"] = results; throw finalException; } return results; }
public IEnumerable<WriteConcernResult> Execute(MongoConnection connection) { WriteConcernException finalException = null; List<WriteConcernResult> results = (WriteConcern.Enabled) ? new List<WriteConcernResult>() : null; using (var bsonBuffer = new BsonBuffer(new MultiChunkBuffer(BsonChunkPool.Default), true)) { var readerSettings = GetNodeAdjustedReaderSettings(connection.ServerInstance); var writerSettings = GetNodeAdjustedWriterSettings(connection.ServerInstance); var message = new MongoInsertMessage(writerSettings, CollectionFullName, _checkElementNames, _flags); message.WriteToBuffer(bsonBuffer); // must be called before AddDocument var writeConcernEnabled = WriteConcern.Enabled; var continueOnError = (_flags & InsertFlags.ContinueOnError) != 0; foreach (var document in _documents) { if (document == null) { throw new ArgumentException("Batch contains one or more null documents."); } if (_assignIdOnInsert) { var serializer = BsonSerializer.LookupSerializer(document.GetType()); var idProvider = serializer as IBsonIdProvider; if (idProvider != null) { object id; Type idNominalType; IIdGenerator idGenerator; if (idProvider.GetDocumentId(document, out id, out idNominalType, out idGenerator)) { if (idGenerator != null && idGenerator.IsEmpty(id)) { id = idGenerator.GenerateId(this, document); idProvider.SetDocumentId(document, id); } } } } message.AddDocument(bsonBuffer, _documentType, document); if (message.MessageLength > connection.ServerInstance.MaxMessageLength) { byte[] lastDocument = message.RemoveLastDocument(bsonBuffer); if (writeConcernEnabled && !continueOnError) { try { var result = SendMessageWithWriteConcern(connection, bsonBuffer, message.RequestId, readerSettings, writerSettings, WriteConcern); results.Add(result); } catch (WriteConcernException ex) { results.Add((WriteConcernResult)ex.CommandResult); ex.Data["results"] = results; throw ex; } } else if (writeConcernEnabled && continueOnError) { try { var result = SendMessageWithWriteConcern(connection, bsonBuffer, message.RequestId, readerSettings, writerSettings, WriteConcern); results.Add(result); } catch (WriteConcernException ex) { finalException = ex; results.Add((WriteConcernResult)ex.CommandResult); } } else if (!writeConcernEnabled && !continueOnError) { try { SendMessageWithWriteConcern(connection, bsonBuffer, message.RequestId, readerSettings, writerSettings, WriteConcern.Acknowledged); } catch (WriteConcernException) { return null; } } else if (!writeConcernEnabled && continueOnError) { SendMessageWithWriteConcern(connection, bsonBuffer, message.RequestId, readerSettings, writerSettings, WriteConcern.Unacknowledged); } message.ResetBatch(bsonBuffer, lastDocument); } } if (writeConcernEnabled) { try { var result = SendMessageWithWriteConcern(connection, bsonBuffer, message.RequestId, readerSettings, writerSettings, WriteConcern); results.Add(result); } catch (WriteConcernException ex) { finalException = ex; results.Add((WriteConcernResult)ex.CommandResult); } if (finalException != null) { finalException.Data["results"] = results; throw finalException; } return results; } else { SendMessageWithWriteConcern(connection, bsonBuffer, message.RequestId, readerSettings, writerSettings, WriteConcern.Unacknowledged); return null; } } }