@@ -38,9 +38,9 @@ public abstract class MongoCollection
38
38
// private fields
39
39
private MongoServer _server ;
40
40
private MongoDatabase _database ;
41
- private MongoDatabase _commandDatabase ; // used to run commands with this collection's settings
42
41
private MongoCollectionSettings _settings ;
43
42
private string _name ;
43
+ private MongoCollection < BsonDocument > _commandCollection ; // used to run commands with this collection's settings
44
44
45
45
// constructors
46
46
/// <summary>
@@ -69,19 +69,16 @@ protected MongoCollection(MongoDatabase database, MongoCollectionSettings settin
69
69
_settings = settings . FrozenCopy ( ) ;
70
70
_name = settings . CollectionName ;
71
71
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
74
72
if ( _name != "$cmd" )
75
73
{
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 ) ;
85
82
}
86
83
}
87
84
@@ -137,7 +134,7 @@ public virtual AggregateResult Aggregate(IEnumerable<BsonDocument> operations)
137
134
{ "aggregate" , _name } ,
138
135
{ "pipeline" , pipeline }
139
136
} ;
140
- return _commandDatabase . RunCommandAs < AggregateResult > ( aggregateCommand ) ;
137
+ return RunCommandAs < AggregateResult > ( aggregateCommand ) ;
141
138
}
142
139
143
140
/// <summary>
@@ -171,7 +168,7 @@ public virtual long Count(IMongoQuery query)
171
168
{ "count" , _name } ,
172
169
{ "query" , BsonDocumentWrapper . Create ( query ) , query != null } // query is optional
173
170
} ;
174
- var result = _commandDatabase . RunCommand ( command ) ;
171
+ var result = RunCommand ( command ) ;
175
172
return result . Response [ "n" ] . ToInt64 ( ) ;
176
173
}
177
174
@@ -247,7 +244,7 @@ public virtual IEnumerable<BsonValue> Distinct(string key, IMongoQuery query)
247
244
{ "key" , key } ,
248
245
{ "query" , BsonDocumentWrapper . Create ( query ) , query != null } // query is optional
249
246
} ;
250
- var result = _commandDatabase . RunCommand ( command ) ;
247
+ var result = RunCommand ( command ) ;
251
248
return result . Response [ "values" ] . AsBsonArray ;
252
249
}
253
250
@@ -314,7 +311,7 @@ public virtual CommandResult DropIndexByName(string indexName)
314
311
} ;
315
312
try
316
313
{
317
- return _commandDatabase . RunCommand ( command ) ;
314
+ return RunCommand ( command ) ;
318
315
}
319
316
catch ( MongoCommandException ex )
320
317
{
@@ -473,7 +470,7 @@ public virtual FindAndModifyResult FindAndModify(
473
470
} ;
474
471
try
475
472
{
476
- return _commandDatabase . RunCommandAs < FindAndModifyResult > ( command ) ;
473
+ return RunCommandAs < FindAndModifyResult > ( command ) ;
477
474
}
478
475
catch ( MongoCommandException ex )
479
476
{
@@ -510,7 +507,7 @@ public virtual FindAndModifyResult FindAndRemove(IMongoQuery query, IMongoSortBy
510
507
} ;
511
508
try
512
509
{
513
- return _commandDatabase . RunCommandAs < FindAndModifyResult > ( command ) ;
510
+ return RunCommandAs < FindAndModifyResult > ( command ) ;
514
511
}
515
512
catch ( MongoCommandException ex )
516
513
{
@@ -654,7 +651,7 @@ public virtual GeoHaystackSearchResult GeoHaystackSearchAs(
654
651
command . Merge ( options . ToBsonDocument ( ) ) ;
655
652
var geoHaystackSearchResultDefinition = typeof ( GeoHaystackSearchResult < > ) ;
656
653
var geoHaystackSearchResultType = geoHaystackSearchResultDefinition . MakeGenericType ( documentType ) ;
657
- return ( GeoHaystackSearchResult ) _commandDatabase . RunCommandAs ( geoHaystackSearchResultType , command ) ;
654
+ return ( GeoHaystackSearchResult ) RunCommandAs ( geoHaystackSearchResultType , command ) ;
658
655
}
659
656
660
657
/// <summary>
@@ -700,7 +697,7 @@ public virtual GeoNearResult<TDocument> GeoNearAs<TDocument>(
700
697
{ "query" , BsonDocumentWrapper . Create ( query ) , query != null } // query is optional
701
698
} ;
702
699
command . Merge ( options . ToBsonDocument ( ) ) ;
703
- return _commandDatabase . RunCommandAs < GeoNearResult < TDocument > > ( command ) ;
700
+ return RunCommandAs < GeoNearResult < TDocument > > ( command ) ;
704
701
}
705
702
706
703
/// <summary>
@@ -745,7 +742,7 @@ public virtual GeoNearResult GeoNearAs(
745
742
command . Merge ( options . ToBsonDocument ( ) ) ;
746
743
var geoNearResultDefinition = typeof ( GeoNearResult < > ) ;
747
744
var geoNearResultType = geoNearResultDefinition . MakeGenericType ( documentType ) ;
748
- return ( GeoNearResult ) _commandDatabase . RunCommandAs ( geoNearResultType , command ) ;
745
+ return ( GeoNearResult ) RunCommandAs ( geoNearResultType , command ) ;
749
746
}
750
747
751
748
/// <summary>
@@ -766,7 +763,7 @@ public virtual GetIndexesResult GetIndexes()
766
763
public virtual CollectionStatsResult GetStats ( )
767
764
{
768
765
var command = new CommandDocument ( "collstats" , _name ) ;
769
- return _commandDatabase . RunCommandAs < CollectionStatsResult > ( command ) ;
766
+ return RunCommandAs < CollectionStatsResult > ( command ) ;
770
767
}
771
768
772
769
/// <summary>
@@ -844,7 +841,7 @@ public virtual IEnumerable<BsonDocument> Group(
844
841
}
845
842
}
846
843
} ;
847
- var result = _commandDatabase . RunCommand ( command ) ;
844
+ var result = RunCommand ( command ) ;
848
845
return result . Response [ "retval" ] . AsBsonArray . Values . Cast < BsonDocument > ( ) ;
849
846
}
850
847
@@ -891,7 +888,7 @@ public virtual IEnumerable<BsonDocument> Group(
891
888
}
892
889
}
893
890
} ;
894
- var result = _commandDatabase . RunCommand ( command ) ;
891
+ var result = RunCommand ( command ) ;
895
892
return result . Response [ "retval" ] . AsBsonArray . Values . Cast < BsonDocument > ( ) ;
896
893
}
897
894
@@ -1219,7 +1216,7 @@ public virtual MapReduceResult MapReduce(
1219
1216
{ "reduce" , reduce }
1220
1217
} ;
1221
1218
command . Add ( options . ToBsonDocument ( ) ) ;
1222
- var result = _commandDatabase . RunCommandAs < MapReduceResult > ( command ) ;
1219
+ var result = RunCommandAs < MapReduceResult > ( command ) ;
1223
1220
result . SetInputDatabase ( _database ) ;
1224
1221
return result ;
1225
1222
}
@@ -1275,7 +1272,7 @@ public virtual MapReduceResult MapReduce(BsonJavaScript map, BsonJavaScript redu
1275
1272
public virtual CommandResult ReIndex ( )
1276
1273
{
1277
1274
var command = new CommandDocument ( "reIndex" , _name ) ;
1278
- return _commandDatabase . RunCommand ( command ) ;
1275
+ return RunCommand ( command ) ;
1279
1276
}
1280
1277
1281
1278
/// <summary>
@@ -1620,7 +1617,7 @@ public virtual SafeModeResult Update(
1620
1617
public virtual ValidateCollectionResult Validate ( )
1621
1618
{
1622
1619
var command = new CommandDocument ( "validate" , _name ) ;
1623
- return _commandDatabase . RunCommandAs < ValidateCollectionResult > ( command ) ;
1620
+ return RunCommandAs < ValidateCollectionResult > ( command ) ;
1624
1621
}
1625
1622
1626
1623
// internal methods
@@ -1642,6 +1639,48 @@ internal BsonBinaryWriterSettings GetWriterSettings(MongoConnection connection)
1642
1639
} ;
1643
1640
}
1644
1641
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
+
1645
1684
// private methods
1646
1685
private string GetIndexName ( BsonDocument keys , BsonDocument options )
1647
1686
{
0 commit comments