[CSHARP-2276] IMongoIndexManager CreateOne or CreateOneAsync methods can throw NullReferenceException Created: 20/May/18  Updated: 28/Oct/23  Resolved: 23/May/18

Status: Closed
Project: C# Driver
Component/s: None
Affects Version/s: 2.7.0
Fix Version/s: 2.7.0

Type: Bug Priority: Major - P3
Reporter: Mohammed Abdel Gader Ibrahim ElAmin [X] Assignee: Robert Stam
Resolution: Fixed Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified
Environment:

Windows 10 64-bit, MongoDB 3.7.9, .NET Core 2.1 RC 1



 Description   

Calling the IMongoIndexManager CreateOne or CreateOneAsync methods and omitting the options argument (or passing null for it) result in a NullReferenceException.

*+Original description+:*

I am using the C# driver 2.7.0-beta0001 and MongoDB 3.7.9 server and I am trying to create multiple indexes on a standalone server using the new transaction feature and I always get an exception:

 

Message "Object reference not set to an instance of an object."
 
Source  "MongoDB.Driver"
 
StackTrace  "at MongoDB.Driver.MongoIndexManagerBase`1.ToCreateManyIndexesOptions(CreateOneIndexOptions options)
at MongoDB.Driver.MongoIndexManagerBase`1.CreateOneAsync(IClientSessionHandle session, CreateIndexModel`1 model, CreateOneIndexOptions options, CancellationToken cancellationToken)
 
TargetSite  {MongoDB.Driver.CreateManyIndexesOptions ToCreateManyIndexesOptions(MongoDB.Driver.CreateOneIndexOptions)}  System.Reflection.MethodBase {System.Reflection.RuntimeMethodInfo}
 
{System.NullReferenceException: Object reference not set to an instance of an object.
at MongoDB.Driver.MongoIndexManagerBase`1.ToCreateManyIndexesOptions(CreateOneIndexOptions options)
at MongoDB.Driver.MongoIndexManagerBase`1.CreateOneAsync(IClientSessionHandle session, CreateIndexModel`1 model, CreateOneIndexOptions options, CancellationToken cancellationToken)

 

Here is my code:

var client = new MongoClient(ConnectionString);
 
var database = client.GetDatabase(DatabaseName);
 
var Coupons = database.GetCollection<Coupon>("Coupons");
 
var Books = database.GetCollection<Book>("Books");
 
var session = await database.Client.StartSessionAsync();
session.StartTransaction();
 
try {
 
     var options = new CreateIndexOptions() { Unique = true };
 
     var couponIndex = new IndexKeysDefinitionBuilder<Coupon>().Ascending(c => c.CouponNumber);
     var couponIndexModel = new CreateIndexModel<Coupon>(couponIndex, options);
     await Coupons.Indexes.CreateOneAsync(session, couponIndexModel);//Exception happens at this line
 
     var bookIndex = new IndexKeysDefinitionBuilder<Book>().Ascending(c => c.BookNumber);
     var bookIndexModel = new CreateIndexModel<Book>(bookIndex, options);
     await Books.Indexes.CreateOneAsync(session, bookIndexModel);
 
     await session.CommitTransactionAsync();
} catch (Exception ex) {
     await session.AbortTransactionAsync();
 
     Console.WriteLine(ex.StackTrace);
}

Even if I didn't use the transactions by removing the session variable, I also get the same exception.

If I used the old deprecated method like in this code I get a different exception:

var couponsIndex = Builders<Coupon>.IndexKeys.Ascending(c => c.CouponNumber);                await Coupons.Indexes.CreateOneAsync(session, couponsIndex, options);

Here is the other exception:

{MongoDB.Driver.MongoCommandException: Command createIndexes failed: Transaction numbers are only allowed on a replica set member or mongos.
   at MongoDB.Driver.Core.WireProtocol.CommandUsingCommandMessageWireProtocol`1.ProcessResponse(ConnectionId connectionId, CommandMessage responseMessage)
   at MongoDB.Driver.Core.WireProtocol.CommandUsingCommandMessageWireProtocol`1.ExecuteAsync(IConnection connection, CancellationToken cancellationToken)
   at MongoDB.Driver.Core.Servers.Server.ServerChannel.ExecuteProtocolAsync[TResult](IWireProtocol`1 protocol, CancellationToken cancellationToken)
   at MongoDB.Driver.Core.Operations.CommandOperationBase`1.ExecuteProtocolAsync(IChannelSource channelSource, ICoreSessionHandle session, ReadPreference readPreference, CancellationToken cancellationToken)
   at MongoDB.Driver.Core.Operations.WriteCommandOperation`1.ExecuteAsync(IWriteBinding binding, CancellationToken cancellationToken)
   at MongoDB.Driver.Core.Operations.CreateIndexesUsingCommandOperation.ExecuteAsync(IWriteBinding binding, CancellationToken cancellationToken)
   at MongoDB.Driver.Core.Operations.CreateIndexesOperation.ExecuteAsync(IWriteBinding binding, CancellationToken cancellationToken)
   at MongoDB.Driver.OperationExecutor.ExecuteWriteOperationAsync[TResult](IWriteBinding binding, IWriteOperation`1 operation, CancellationToken cancellationToken)
   at MongoDB.Driver.MongoCollectionImpl`1.ExecuteWriteOperationAsync[TResult](IClientSessionHandle session, IWriteOperation`1 operation, CancellationToken cancellationToken)
   at MongoDB.Driver.MongoCollectionImpl`1.MongoIndexManager.CreateManyAsync(IClientSessionHandle session, IEnumerable`1 models, CreateManyIndexesOptions options, CancellationToken cancellationToken)
   at MongoDB.Driver.MongoIndexManagerBase`1.CreateOneAsync(IClientSessionHandle session, IndexKeysDefinition`1 keys, CreateIndexOptions options, CancellationToken cancellationToken)

 



 Comments   
Comment by Githook User [ 23/May/18 ]

Author:

{'username': 'rstam', 'name': 'rstam', 'email': 'robert@robertstam.org'}

Message: CSHARP-2276: IMongoIndexManager CreateOne or CreateOneAsync methods can throw NullReferenceException
Branch: master
https://github.com/mongodb/mongo-csharp-driver/commit/ac83d02e7ce64cbd63ac06eb4da213872979e564

Comment by Robert Stam [ 22/May/18 ]

Additional note: I don't think create index (single or multiple) can be run inside a transaction.

 

Comment by Robert Stam [ 22/May/18 ]

Just noticed in your original description that you mention you are testing against a standalone. Standalones do not support transactions.

If you want to test transactions you can use a single member replica set.

Also, not everything transaction related works yet in server 3.7.9. You might possibly need to test against a newer version of the server.

Comment by Robert Stam [ 22/May/18 ]

I can reproduce this. The issue is related to the options parameter of CreateOneAsync being omitted (which results in the default value of null).

You can work around this by replacing:

await Coupons.Indexes.CreateOneAsync(session, couponIndexModel);//Exception happens at this line 

with:

var options = new CreateOneIndexOptions();
await Coupons.Indexes.CreateOneAsync(session, couponIndexModel, options ); // don't let options default to null

As for the other exception, transactions are currently only supported on replica sets. What deployment type are you testing against?

 

Generated at Wed Feb 07 21:42:06 UTC 2024 using Jira 9.7.1#970001-sha1:2222b88b221c4928ef0de3161136cc90c8356a66.