Martin
Martin

Reputation: 67

How to use C# to insert document into existing embedded documents?

I have the structure below in C# (a customer with invoices). I'm struggling to insert into an existing mongodb record. I'm using C# .NET 4.5 together with MongoDB 2.4. I would like to insert a new invoice into an existing customer record.

I receive the error "duplicate key error" which I understand but I don't know how to append to the Invoices object within the Customer object.

Any help much appreciated.

My attempt

var client = new MongoClient();
var database = client.GetDatabase("databasename");
var collection = database.GetCollection<Customer>("Customer");


var customerId = "..";
var builder = Builders<Customer>.Filter;
var filter = builder.Eq("Id", new ObjectId(customerId));
var matchedRecord = collection.Find(filter).SingleOrDefault();

// Insert new invoice into the customer record
matchedRecord.Invoices.Add(new Invoice {
  InvoiceNumber = "123456"
});

collection.InsertOne(matchedRecord);  // Error produced below

Error

E11000 duplicate key error collection: databasename.Customer index: _id_ dup key: { : ObjectId('..') }

Classes

public class Customer
{
    public ObjectId Id { get; set; }

    public string CustomerId { get; set; }

    public List<Invoice> Invoices { get; set; }
}

public class Invoice
{
    public string InvoiceNumber { get; set; }
}

Update

var builder = Builders<Customer>.Filter;
var filter = builder.Eq("Id", new ObjectId(customerId));

// Not sure how to use the FindOneAndUpdate method(?)
var matchedRecord = collection.FindOneAndUpdate<Customer>(filter);

Second update

I've tried the following but it inserts a new invoice object (outside Invoices)

var builder = Builders<Customer>.Filter;
var filter = builder.Eq("Id", new ObjectId(customerId));
var update = Builders<Customer>.Update.Set("Invoice.ClientName", "HELLO");

Third update

This approach overwrites the customer's existing invoices and replaces it with this "hello" invoice. How can you append to the existing invoices..?

var update = Builders<Customer>.Update
            .Set("Invoices", new Invoice
            {
                ClientName = "HELLO"
            });

        var result = collection.UpdateOneAsync(filter, update);

Upvotes: 1

Views: 2026

Answers (1)

Martin
Martin

Reputation: 67

This works, notice the use of Push - otherwise it's the same as the set approach above (see third update)

var update = Builders<Customer>.Update.Push("Invoices", new Invoice
            {
                ClientName = "HELLO"
            });

var result = collection.UpdateOneAsync(filter, update);

Upvotes: 2

Related Questions