title: Mongodb FindOneAndUpdate in .NET not thread safe?
body: <p>I'm trying to create a unique counter table. To update the counter in the table I tried using FindOneAndUpdate. At first everything seem to work as planned so I figured I would stress test it. I created a process that gets a counter 20,000 and executed that counter on 5 threads. Sure enough, I end up with duplicates.
  I'm running this against a single, local db; however the production db is a replica set.</p>
  
  <pre><code>static void Main(string[] args)
  {       
      Console.WriteLine("Press Enter to begin...");
      Console.ReadLine();
  
          int numOfThreads = 10;
          var tasks = new List&lt;Task&gt;();
          for (int i = 0; i &lt; numOfThreads; i++)            
              tasks.Add(Task.Run(() =&gt; TestWrites()));
  
          Console.WriteLine($"Waiting for {tasks.Count} tasks to complete...");
          Task.WaitAll(tasks.ToArray());
          Console.WriteLine("Done. Press Enter to exit.");
          Console.ReadLine();
  }
  
  private static void TestWrites()
  {
      var tester = new ConcurrentTester();
      int writes = 20000;
      for (int i = 0; i &lt; writes; i++)
          tester.InsertCounter(tester.GetCounter());
  
      Console.WriteLine($"Wrote {writes}");
  }
  
  public class ConcurrentTester
  {
      private IMongoDatabase database;
  
      public ConcurrentTester()
      {
          var connStr = "";
          var mongoClient = new MongoClient(connStr);
  
          database = mongoClient.GetDatabase("test");
      }
  
      public int GetCounter()
      {
          var collection = database.GetCollection&lt;InternalCounter&gt;("Concurrency");
          var filter = Builders&lt;InternalCounter&gt;.Filter.Eq("CounterName", "Test");
          var mkt = collection.Find(filter).FirstOrDefault();
  
          var options = new FindOneAndUpdateOptions&lt;InternalCounter&gt; { IsUpsert = true, ReturnDocument = ReturnDocument.After };
          InternalCounter ctn = collection.FindOneAndUpdate(filter, 
              Builders&lt;InternalCounter&gt;.Update.Inc(s =&gt; s.CounterValue, 1), options);
          return ctn.CounterValue;
      }
  }
  
  public class InternalCounter
  {
      public InternalCounter()
      {
          _id = ObjectId.GenerateNewId();
      }
  
      public object _id { get; set; }
  
      public string CounterName { get; set; }
      public int CounterValue { get; set; }
  }
  </code></pre>
  
  <p><strong>Update</strong></p>
  
  <p>Since this code is in our service, I added a lock to prevent concurrent calls. This is only a stop gap until I can figure out what's going on in MongoDb.</p>
  
  <pre><code>lock (sync)
  {
      ctn = collection.FindOneAndUpdate(filter,
          Builders&lt;InternalCounter&gt;.Update.Inc(s =&gt; s.CounterValue, 1), options);
  }
  </code></pre>
  
  <p><strong>Update 2</strong></p>
  
  <p>I see there is also a findAndModify method but it's not implemented in the C# lib. From it's description it sounds like it supposed to do the same as findOneAndUpdate.
  I also read that findOneAndUpdate replaced findAndModify. Is this true?</p>
  
  <p><strong>Update 3</strong>
  After further consideration, my lock isn't going to work. It will work when there is only a single instance but with load balancing, there are multiple instances and that can't be fixed with a lock.</p>