Skip to content

Commit 6be0e77

Browse files
author
rstam
committed
CSHARP-580: alternative implementation that doesn't involve MongoCollection creating a new instance of MongoDatabase.
1 parent a6eafbd commit 6be0e77

File tree

2 files changed

+67
-46
lines changed

2 files changed

+67
-46
lines changed

Driver/Core/MongoCollection.cs

+66-27
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,9 @@ public abstract class MongoCollection
3838
// private fields
3939
private MongoServer _server;
4040
private MongoDatabase _database;
41-
private MongoDatabase _commandDatabase; // used to run commands with this collection's settings
4241
private MongoCollectionSettings _settings;
4342
private string _name;
43+
private MongoCollection<BsonDocument> _commandCollection; // used to run commands with this collection's settings
4444

4545
// constructors
4646
/// <summary>
@@ -69,19 +69,16 @@ protected MongoCollection(MongoDatabase database, MongoCollectionSettings settin
6969
_settings = settings.FrozenCopy();
7070
_name = settings.CollectionName;
7171

72-
// note: if the settings are compatible _commandDatabase will end up being the same instance as _database
73-
// need to check for $cmd to avoid infinite recursion
7472
if (_name != "$cmd")
7573
{
76-
var commandDatabaseSettings = _database.Settings.Clone();
77-
commandDatabaseSettings.GuidRepresentation = _settings.GuidRepresentation;
78-
commandDatabaseSettings.ReadPreference = _settings.ReadPreference;
79-
commandDatabaseSettings.SafeMode = _settings.SafeMode; // not really relevant to commands since they are all queries anyway
80-
_commandDatabase = _server.GetDatabase(commandDatabaseSettings);
81-
}
82-
else
83-
{
84-
_commandDatabase = _database;
74+
var commandCollectionSettings = new MongoCollectionSettings<BsonDocument>(_database, "$cmd")
75+
{
76+
AssignIdOnInsert = false,
77+
GuidRepresentation = _settings.GuidRepresentation,
78+
ReadPreference = _settings.ReadPreference,
79+
SafeMode = _settings.SafeMode
80+
};
81+
_commandCollection = _database.GetCollection(commandCollectionSettings);
8582
}
8683
}
8784

@@ -137,7 +134,7 @@ public virtual AggregateResult Aggregate(IEnumerable<BsonDocument> operations)
137134
{ "aggregate", _name },
138135
{ "pipeline", pipeline }
139136
};
140-
return _commandDatabase.RunCommandAs<AggregateResult>(aggregateCommand);
137+
return RunCommandAs<AggregateResult>(aggregateCommand);
141138
}
142139

143140
/// <summary>
@@ -171,7 +168,7 @@ public virtual long Count(IMongoQuery query)
171168
{ "count", _name },
172169
{ "query", BsonDocumentWrapper.Create(query), query != null } // query is optional
173170
};
174-
var result = _commandDatabase.RunCommand(command);
171+
var result = RunCommand(command);
175172
return result.Response["n"].ToInt64();
176173
}
177174

@@ -247,7 +244,7 @@ public virtual IEnumerable<BsonValue> Distinct(string key, IMongoQuery query)
247244
{ "key", key },
248245
{ "query", BsonDocumentWrapper.Create(query), query != null } // query is optional
249246
};
250-
var result = _commandDatabase.RunCommand(command);
247+
var result = RunCommand(command);
251248
return result.Response["values"].AsBsonArray;
252249
}
253250

@@ -314,7 +311,7 @@ public virtual CommandResult DropIndexByName(string indexName)
314311
};
315312
try
316313
{
317-
return _commandDatabase.RunCommand(command);
314+
return RunCommand(command);
318315
}
319316
catch (MongoCommandException ex)
320317
{
@@ -473,7 +470,7 @@ public virtual FindAndModifyResult FindAndModify(
473470
};
474471
try
475472
{
476-
return _commandDatabase.RunCommandAs<FindAndModifyResult>(command);
473+
return RunCommandAs<FindAndModifyResult>(command);
477474
}
478475
catch (MongoCommandException ex)
479476
{
@@ -510,7 +507,7 @@ public virtual FindAndModifyResult FindAndRemove(IMongoQuery query, IMongoSortBy
510507
};
511508
try
512509
{
513-
return _commandDatabase.RunCommandAs<FindAndModifyResult>(command);
510+
return RunCommandAs<FindAndModifyResult>(command);
514511
}
515512
catch (MongoCommandException ex)
516513
{
@@ -654,7 +651,7 @@ public virtual GeoHaystackSearchResult GeoHaystackSearchAs(
654651
command.Merge(options.ToBsonDocument());
655652
var geoHaystackSearchResultDefinition = typeof(GeoHaystackSearchResult<>);
656653
var geoHaystackSearchResultType = geoHaystackSearchResultDefinition.MakeGenericType(documentType);
657-
return (GeoHaystackSearchResult)_commandDatabase.RunCommandAs(geoHaystackSearchResultType, command);
654+
return (GeoHaystackSearchResult)RunCommandAs(geoHaystackSearchResultType, command);
658655
}
659656

660657
/// <summary>
@@ -700,7 +697,7 @@ public virtual GeoNearResult<TDocument> GeoNearAs<TDocument>(
700697
{ "query", BsonDocumentWrapper.Create(query), query != null } // query is optional
701698
};
702699
command.Merge(options.ToBsonDocument());
703-
return _commandDatabase.RunCommandAs<GeoNearResult<TDocument>>(command);
700+
return RunCommandAs<GeoNearResult<TDocument>>(command);
704701
}
705702

706703
/// <summary>
@@ -745,7 +742,7 @@ public virtual GeoNearResult GeoNearAs(
745742
command.Merge(options.ToBsonDocument());
746743
var geoNearResultDefinition = typeof(GeoNearResult<>);
747744
var geoNearResultType = geoNearResultDefinition.MakeGenericType(documentType);
748-
return (GeoNearResult)_commandDatabase.RunCommandAs(geoNearResultType, command);
745+
return (GeoNearResult)RunCommandAs(geoNearResultType, command);
749746
}
750747

751748
/// <summary>
@@ -766,7 +763,7 @@ public virtual GetIndexesResult GetIndexes()
766763
public virtual CollectionStatsResult GetStats()
767764
{
768765
var command = new CommandDocument("collstats", _name);
769-
return _commandDatabase.RunCommandAs<CollectionStatsResult>(command);
766+
return RunCommandAs<CollectionStatsResult>(command);
770767
}
771768

772769
/// <summary>
@@ -844,7 +841,7 @@ public virtual IEnumerable<BsonDocument> Group(
844841
}
845842
}
846843
};
847-
var result = _commandDatabase.RunCommand(command);
844+
var result = RunCommand(command);
848845
return result.Response["retval"].AsBsonArray.Values.Cast<BsonDocument>();
849846
}
850847

@@ -891,7 +888,7 @@ public virtual IEnumerable<BsonDocument> Group(
891888
}
892889
}
893890
};
894-
var result = _commandDatabase.RunCommand(command);
891+
var result = RunCommand(command);
895892
return result.Response["retval"].AsBsonArray.Values.Cast<BsonDocument>();
896893
}
897894

@@ -1219,7 +1216,7 @@ public virtual MapReduceResult MapReduce(
12191216
{ "reduce", reduce }
12201217
};
12211218
command.Add(options.ToBsonDocument());
1222-
var result = _commandDatabase.RunCommandAs<MapReduceResult>(command);
1219+
var result = RunCommandAs<MapReduceResult>(command);
12231220
result.SetInputDatabase(_database);
12241221
return result;
12251222
}
@@ -1275,7 +1272,7 @@ public virtual MapReduceResult MapReduce(BsonJavaScript map, BsonJavaScript redu
12751272
public virtual CommandResult ReIndex()
12761273
{
12771274
var command = new CommandDocument("reIndex", _name);
1278-
return _commandDatabase.RunCommand(command);
1275+
return RunCommand(command);
12791276
}
12801277

12811278
/// <summary>
@@ -1620,7 +1617,7 @@ public virtual SafeModeResult Update(
16201617
public virtual ValidateCollectionResult Validate()
16211618
{
16221619
var command = new CommandDocument("validate", _name);
1623-
return _commandDatabase.RunCommandAs<ValidateCollectionResult>(command);
1620+
return RunCommandAs<ValidateCollectionResult>(command);
16241621
}
16251622

16261623
// internal methods
@@ -1642,6 +1639,48 @@ internal BsonBinaryWriterSettings GetWriterSettings(MongoConnection connection)
16421639
};
16431640
}
16441641

1642+
internal CommandResult RunCommand(IMongoCommand command)
1643+
{
1644+
return RunCommandAs<CommandResult>(command);
1645+
}
1646+
1647+
internal TCommandResult RunCommandAs<TCommandResult>(IMongoCommand command)
1648+
where TCommandResult : CommandResult, new()
1649+
{
1650+
return (TCommandResult)RunCommandAs(typeof(TCommandResult), command);
1651+
}
1652+
1653+
internal CommandResult RunCommandAs(Type commandResultType, IMongoCommand command)
1654+
{
1655+
// if necessary delegate running the command to the _commandCollection
1656+
if (_name == "$cmd")
1657+
{
1658+
var response = FindOneAs<BsonDocument>(command);
1659+
if (response == null)
1660+
{
1661+
var commandName = command.ToBsonDocument().GetElement(0).Name;
1662+
var message = string.Format("Command '{0}' failed. No response returned.", commandName);
1663+
throw new MongoCommandException(message);
1664+
}
1665+
var commandResult = (CommandResult)Activator.CreateInstance(commandResultType); // constructor can't have arguments
1666+
commandResult.Initialize(command, response); // so two phase construction required
1667+
if (!commandResult.Ok)
1668+
{
1669+
if (commandResult.ErrorMessage == "not master")
1670+
{
1671+
// TODO: figure out which instance gave the error and set its state to Unknown
1672+
_server.Disconnect();
1673+
}
1674+
throw new MongoCommandException(commandResult);
1675+
}
1676+
return commandResult;
1677+
}
1678+
else
1679+
{
1680+
return _commandCollection.RunCommandAs(commandResultType, command);
1681+
}
1682+
}
1683+
16451684
// private methods
16461685
private string GetIndexName(BsonDocument keys, BsonDocument options)
16471686
{

Driver/Core/MongoDatabase.cs

+1-19
Original file line numberDiff line numberDiff line change
@@ -970,25 +970,7 @@ public virtual TCommandResult RunCommandAs<TCommandResult>(string commandName)
970970
/// <returns>A TCommandResult</returns>
971971
public virtual CommandResult RunCommandAs(Type commandResultType, IMongoCommand command)
972972
{
973-
var response = CommandCollection.FindOne(command);
974-
if (response == null)
975-
{
976-
var commandName = command.ToBsonDocument().GetElement(0).Name;
977-
var message = string.Format("Command '{0}' failed. No response returned.", commandName);
978-
throw new MongoCommandException(message);
979-
}
980-
var commandResult = (CommandResult)Activator.CreateInstance(commandResultType); // constructor can't have arguments
981-
commandResult.Initialize(command, response); // so two phase construction required
982-
if (!commandResult.Ok)
983-
{
984-
if (commandResult.ErrorMessage == "not master")
985-
{
986-
// TODO: figure out which instance gave the error and set its state to Unknown
987-
_server.Disconnect();
988-
}
989-
throw new MongoCommandException(commandResult);
990-
}
991-
return commandResult;
973+
return CommandCollection.RunCommandAs(commandResultType, command);
992974
}
993975

994976
/// <summary>

0 commit comments

Comments
 (0)