NULL ObjectId in C# driver

4,542 views
Skip to first unread message

Khash

unread,
Nov 21, 2010, 7:16:04 AM11/21/10
to mongodb-user
Having a property of type ObjectId on a class means it can be set to
null. This does not stop the server from inserting it as a document
and also using the command line retrieving it.

However, such object cannot be retrieved using the C# driver as it
complains that BsonType cannot be null.

To reproduce this, add a property of type ObjectId to a class. Set the
value of this property to null and save it to the db.

Using the command line tool, do a find and you'll see it can be
retrieved from the db. However, trying to perform a find using the C#
driver causes an exception.

Robert Stam

unread,
Nov 21, 2010, 12:20:29 PM11/21/10
to mongodb-user
Which driver are you using?

In the 10gen C# Driver ObjectId is a struct and could therefore never
be null. So I'm not sure I understand how to reproduce what you are
describing.

Andrew Rondeau

unread,
Nov 21, 2010, 4:26:33 PM11/21/10
to mongodb-user
ObjectId is a struct, you can't set a struct to null. (Just like you
can't set an int, long, double, ect to null.)

You can do:
private ObjectId _id = default(ObjectId);
private ObjectId? _id = null;

In the case of default(ObjectId), my understanding is that the runtime
will will initialize the memory to contain all zeros.

Perhaps you're hitting an issue with boxing where the struct is
transparently put into an object:

object boxed = new ObjectId();
ObjectId unboxed = (ObjectId)boxed;

Khash

unread,
Nov 23, 2010, 9:04:27 AM11/23/10
to mongodb-user
I appreciate that ObjectId is a struct. But that's only the case in
this driver and not necessarily other drivers/languages. And certainly
MongoDb does not stop you from assigning it to null.

Therefore it is possible (as it has happened to me, moving from
another driver to this), to try and load a null into an ObjectId for a
document that is saved by another driver/language.

Robert Stam

unread,
Nov 23, 2010, 9:42:19 AM11/23/10
to mongodb-user
You can use Andrew's suggestion to use ObjectId? for your C# data
type.

Here's a sample program:

File at: https://gist.github.com/4bb33e2c799a6865b71b

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using MongoDB.Bson;
using MongoDB.Driver;

namespace NullObjectId {
public class C {
public ObjectId? Id;
public ObjectId? Property;
}

public static class Program {
public static void Main(string[] args) {
var server = MongoServer.Create("mongodb://localhost/?
safe=true");
var database = server["test"];
var collection = database.GetCollection<C>("test");

collection.RemoveAll();
collection.Insert(new C { Id = null, Property = null });
collection.Insert(new C { Id = ObjectId.GenerateNewId(),
Property = null });
collection.Insert(new C { Id = ObjectId.GenerateNewId(),
Property = ObjectId.GenerateNewId() });

foreach (var document in collection.FindAll()) {
Console.WriteLine("Id = {0}, Property = {1}",
document.Id, document.Property);

Andrew Rondeau

unread,
Nov 24, 2010, 5:09:01 PM11/24/10
to mongodb-user
In .Net, Guid is a struct. (Guid is the closest thing to an ObjectId,
except it's 16 bytes ad has different generation logic.)

I've personally advocated for ObjectId (and Oid in Samus's driver) to
be a struct to keep in line with .Net semantics for Guid, and because
the "?" syntax lets you box it as an object that can be null.

Generally-speaking, structs are always copied by value when assigned
to another object, as opposed to being maintained on the heap. This
has implications for garbage collection when your objects make it to
generation 2 in that structs don't need to be collected. Of course,
you can always box structs with "?" if you want real objects.
Reply all
Reply to author
Forward
0 new messages