13

I am able to update a Document if the Document Exists using the Following

var filter = Builders<Neighborhood>.Filter.Eq(x => x.Id, neighborhood.Id); var result = await collection.ReplaceOneAsync(filter, neighborhood,new UpdateOptions { IsUpsert = true }); [CollectionName("neighborhoods")] [BsonIgnoreExtraElements(true)] public class Neighborhood : IEntity<string> { [BsonId(IdGenerator = typeof(GuidGenerator))] [BsonRepresentation(BsonType.ObjectId)] public string Id { get; set; } [BsonElement("name")] public string Name { get; set; } } 

How do Insert a Document if the Id = NULL and I want to return the updated result.

When Inserting a New Document NULL ID, A Record is created with a NULL Id, I added [BsonId(IdGenerator = typeof(GuidGenerator))] without any luck.

What am I doing wrong so a ObjectId can be generated for new records.

3
  • 1
    Possible duplicate of Upserting in Mongo DB using official C# driver Commented Jan 3, 2016 at 6:32
  • I modified the question, this issue is related to the Object Id not be generated Commented Jan 3, 2016 at 22:29
  • This is not a duplicate Commented Mar 24, 2021 at 10:23

1 Answer 1

11

C# Driver thinks that Id is already filled. You need to add settings for Id field which allows driver to generate new Id.
There are two approaches:

  1. Add attribute [BsonIgnoreIfDefault] in your Neighborhood model.
  2. Setup in code

    BsonClassMap.RegisterClassMap<Neighborhood>(x => { x.AutoMap(); x.GetMemberMap(m => m.Id).SetIgnoreIfDefault(true); }); 

I prefer the second approach because you don't need to add reference to MongoDB.

MongoDB API proposes two methods:
1) ReplaceOneAsync returns ReplaceOneResult which has UpsertedId property

var filter = Builders<Neighborhood>.Filter.Where(x => x.Name == "somthing"); var replaceResult = await collection.ReplaceOneAsync(filter, entity, new UpdateOptions { IsUpsert = true }); return replaceResult.UpsertedId; 

2) FindOneAndReplaceAsync allows you to select what you want - entity before changes or after. For our task we need after

var filter = Builders<Neighborhood>.Filter.Where(x => x.Name == "somthing"); var options = new FindOneAndReplaceOptions<Neighborhood, Neighborhood> { IsUpsert = true, ReturnDocument = ReturnDocument.After }; var updatedEntity = await collection.FindOneAndReplaceAsync(filter, entity, options); 
Sign up to request clarification or add additional context in comments.

4 Comments

Thanks, This Should help, Still not getting the Id to Generate, there may be other issues I need to look at
@SPS101, try FindOneAndReplaceAsync. I added an example to the answer.
Thanks, for the help, For Some Reason on Save the Id is generated, but on other commands the Id is not generated, So I am manually setting the objectId when null, still a work in progress but I can move forward. Thanks Again
Neither FindOneAndReplace or ReplaceOneAsync will set the the [BsonRepresentation(BsonType.ObjectId)] property, even with the [BsonIgnoreIfDefault] attribute.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.