[CSHARP-1549] findOneAndUpdate - C# duplicate key error Created: 29/Jan/16  Updated: 05/Apr/19  Resolved: 02/Feb/16

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

Type: Task Priority: Minor - P4
Reporter: Patrick Sheehan Assignee: Robert Stam
Resolution: Done Votes: 0
Labels: c#, question
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified
Environment:

Visual Studio 2015 with Mongo C# Client 2.2.2
MongoDB 3.2.1 / 64 bit on Windows Server 2012 R2


Attachments: JPEG File C#_Exception.jpeg    

 Description   

InnerException: "An item with the same key has already been added"

using MongoDB.Bson.Serialization;
using MongoDB.Driver;
 
namespace MongoCounterDemo
{
    class Program
    {
        private const string ConnectionString = "mongodb://user:password@host:27017/database";
 
        static void Main(string[] args)
        {
            var customerCounter = new MongoDbCounter(ConnectionString, "Customers");
            customerCounter.GetNextNumber();
        }
    }
 
    class MongoDbCounter
    {
        #region Constants
 
        private const string CounterCollectionName = "Counters";
 
        #endregion
 
        #region Fields
 
        private readonly string _connectionString;
        private readonly string _counterName;
 
        #endregion
 
        #region Constructor
 
        public MongoDbCounter(string connectionString, string counterName)
        {
            _connectionString = connectionString;
            _counterName = counterName;
        }
 
        #endregion
 
        #region Public Methods
 
        public int GetNextNumber()
        {
            var client = new MongoClient(_connectionString);
            var databaseName = new MongoUrl(_connectionString).DatabaseName;
            var db = client.GetDatabase(databaseName);
            var counterCol = db.GetCollection<Counter>(CounterCollectionName); 
            var filter2 = Builders<Counter>.Filter.Eq("_id", _counterName);
            var update2 = Builders<Counter>.Update.Inc(c => c.Value, 1);
            var options2 = new FindOneAndUpdateOptions<Counter> { IsUpsert = true, ReturnDocument = ReturnDocument.After};
            var result2 = counterCol.FindOneAndUpdate(filter2, update2, options2);
 
            return result2.Value;
        }
 
        #endregion
    }
 
    class Counter
    {
        static Counter()
        {
            BsonClassMap.RegisterClassMap<Counter>(cm =>
            {
                cm.MapIdMember(c => c.Id);
                cm.MapProperty(c => c.Value);
            });
        }
 
        public string Id { get; set; }
        public int Value { get; set; }
    }
}



 Comments   
Comment by Robert Stam [ 02/Feb/16 ]

Thanks for letting us know.

Comment by Patrick Sheehan [ 02/Feb/16 ]

The customer has removed the static constructor and now everything works as expected. Thanks for the assistance! You may close this ticket as resolved.

Comment by Robert Stam [ 29/Jan/16 ]

Thanks for providing the code to reproduce this. That made it much easier for me to figure out what is happening.

Static constructors are not a good place to be calling RegisterClassMap from, because you have no control over when the static constructor is called.

In this case by the time your static constructor is called the driver has already automatically registered a class map for the Counter class, so your call to RegisterClassMap results in a duplicate key error.

If you need to call RegisterClassMap be sure to do so as early as possible in the startup code of your application to make sure it gets registered before the driver encounters the need to automatically register one.

In this particular sample application, you don't even need to call RegisterClassMap at all because the defaults will do the same thing that your call to RegisterClassMap is doing.

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