Search code examples
c#mongodbmongodb-querymongodb-.net-drivermongodb-csharp-2.0

Mongodb c sharp driver document update error


I am using c# mongo db driver to insert and update a document. First i insert a record and then I try to update a specific field of record using FindOneAndUpdateAsync method. I am able to update it properly but after update I am getting a error "Required element 'Name' for property 'Name' of class SampleApp.Person is missing." I am using MongoCommunity edition 4.4.1 and mongo driver is 2.11.4.

I am attaching image of mongo compass view for your reference.Compass View

My collection structure is

[BsonSerializer(typeof(ImpliedImplementationInterfaceSerializer<IPerson, Person>))]
public interface IPerson
{
    string Id { get; set; }
    string Name { get; set; }
    int Age { get; set; }
    string Email { get; set; }
    IAddress Address { get; set; }
    bool IsActive { get; set; }
}

public class Person : IPerson
{
    [BsonId]
    public string Id { get; set; }

    [BsonRequired]
    
    public string Name { get; set; }

    [BsonRequired]
    public int Age { get; set; }
    public string Email { get; set; }
    public IAddress Address { get; set; }

    [BsonRequired]
    public bool IsActive { get; set; }
}

public interface IAddress
{
    string Line1 { get; set; }
    string Line2 { get; set; }
    string Line3 { get; set; }
    string City { get; set; }
    string State { get; set; }
    string Pincode { get; set; }
}

public class Address : IAddress
{
    public string Line1 { get; set; }
    public string Line2 { get; set; }
    public string Line3 { get; set; }
    public string City { get; set; }
    public string State { get; set; }
    public string Pincode { get; set; }
}

My code to insert and update is as shown below.

MongoClient client = new MongoClient("mongodb://localhost:27017");
var database = client.GetDatabase("test");
BsonClassMap.RegisterClassMap<Address>();
var peopleCollection = database.GetCollection<IPerson>("People");
IPerson person = new Person()
{
    Age = 50,
    Email = "a@a.com",
    IsActive = false,
    Name = "David",
    Id = ObjectId.GenerateNewId().ToString()
};
try
{
    await peopleCollection.InsertOneAsync(person);
    IAddress address = new Address()
    {
        City = "Bengaluru",
        Line1 = "Bengaluru",
        Line2 = "Bengaluru",
        Line3 = "Bengaluru",
        Pincode = "560001",
        State = "KA"
    };

    var updateDefinition = Builders<IPerson>.Update.Set(x => x.Address, address).Set(x => 
    x.IsActive, true);
    var filter = Builders<IPerson>.Filter.Eq(x => x.Email, "a@a.com");
    FindOneAndUpdateOptions<IPerson> updateOptions = new FindOneAndUpdateOptions<IPerson>
    {
        IsUpsert = false,
        ReturnDocument = ReturnDocument.After,
        Projection = Builders<IPerson>.Projection.Include(c => c.Address)
    };
    IPerson updatedPerson = await peopleCollection.FindOneAndUpdateAsync(filter, updateDefinition, updateOptions);

    }
    catch (Exception ex)
    {
       string s = ex.Message;
       Console.WriteLine(s);
    }

Solution

  • My guess is that the value pre-update, does not have the Name property at all, so when the FindOneAndUpdateAsync gets the data and tries to deserialize it (before updating) it fails with that error.

    Two solutions for this

    1. Try removing the [BsonRequired] so that youy avoid this error.
    2. Try to update all the documents in the MongoDB instance, to have the Name property, before running your code.