C# Update Array of objects

386 views
Skip to first unread message

Ed Rooth

unread,
Nov 22, 2010, 2:52:05 AM11/22/10
to mongodb-user
Sorry, but I haven't found any examples of how to update arrays of non-
value type items. I have a schema like below:

{
_id: ...,
field1: ...,
field2...,
myInnerObjects: [{foo: 'bar', x: 2}, {foo: 'blah', x: 3}]
}

Saving and retrieving the main objects (containing the inner ones)
works just fine. However I want to be able to do update/push/
AddToSetEach etc to myInnerObjects. As an example AddToSetEach()
expects a BsonValue[] array. I've tried various methods and can't get
my inner objects to serialize into the appropriate form.

So finally I'm doing the following:

var bsonDocs = myObjList.ConvertAll(obj =>
obj.ToBsonDocument()).ToArray();
var update = Update.AddToSetEach("InnerObjects", bsonDocs);
myCollection.Update(query, update, UpdateFlags.None, SafeMode.True);


which works, but now it's storing the type field (_t) for each inner
object which I don't really think is necessary. Is there a better way
to do this? It seems like the custom object-to-bsonvalue conversion is
the hard part. How would one go about serializing an object to a
document fragment?

Of course the ultimate in convenience would be if there were an API
method like:

Update.AddToSetEach(string name, IEnumerable<T> values);

Robert Stam

unread,
Nov 22, 2010, 10:23:53 AM11/22/10
to mongodb-user
Good question. I will look into making AddToSetEach work more
seamlessly with custom C# types. I've created a JIRA case for this:

http://jira.mongodb.org/browse/CSHARP-111

In the meantime, here's a bit of a hack you can use, replace your call
to:

obj.ToBsonDocument()

with

// where FooBar is the class of your inner objects
BsonSerializer.Deserialize<BsonDocument>(obj.ToBson<FooBar>())

The serializer decides that a "_t" discriminator is needed when the
actual type being serialized is different from the "nominal" type. In
your call to ToBsonDocument the nominal type is object but the actual
type is FooBar In the second form we are removing the need for a
discriminator by calling ToBson<FooBar>, which sets the nominal type
to FooBar.

I probably should add an overload of ToBsonDocument that looks like
this:

obj.ToBsonDocument<FooBar>()

which would do the same thing internally.

And of course enhancing AddToSetEach is also a great idea.

Thanks for the feedback.

Robert Stam

unread,
Nov 22, 2010, 10:34:09 AM11/22/10
to mongodb-user
I've added a unit test for this: CSharp111Tests.cs under
DriverOnlineTests.

At the moment the unit test just tests the workaround I recommended.

Ed Rooth

unread,
Dec 6, 2010, 8:49:10 PM12/6/10
to mongodb-user
I noticed you created a new method called AddToSetWrapped(). That's
pretty handy. Would be nice if there were similar methods for Push()
and Pull() etc.
Reply all
Reply to author
Forward
0 new messages