how to manage _id field when using POCO with mongodb c# driver

41,684

Solution 1

When you insert an object, if it doesn't have an _id field then the driver adds one and sets it to a 12-byte MongoDB ObjectId value.

You just need to add an Id property to your POCO, which will be deserialised from _id:

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

Or, if you'd like to delegate another property to map onto _id then you can decorate it with the BsonIdAttribute, like this:

[BsonId]
public ObjectId MyKey { get; set; }   

The _id field doesn't have to be an MongoDB ObjectId, you can set it to any value of any data type (except an array), it just needs to be unique within the collection.

Solution 2

You have to add a property (or field) for id and tell serializer which id generator you'd like to use.

[BsonId(IdGenerator = typeof(ObjectIdGenerator))]
public object ThingyId { get; set; }

There are 3 available in MongoDb Driver or you can write your own. More info at http://www.mongodb.org/display/DOCS/CSharp+Driver+Serialization+Tutorial#CSharpDriverSerializationTutorial-WriteacustomIdgenerator

Solution 3

I generally wrap Thingy:

public class MongoThingy
{
    public ObjectId Id { get; set; }
    public Thingy Thingy { get; set; }
}

It makes it a lot easier, as often times class Thingy comes from a different library over which I have no control. It's also easier to deserialize in order to hand it over to someone else for processsing.

Solution 4

Add a property as follows:

public BsonObjectId Id { get; set; }

The MongoDB driver automatically converts Id to _id during serialization\deserializtion.

Solution 5

public class Thingy
{
      public ObjectId Id { get; set; }
      public string Foo { get; set; }
}

According to class

Where needed, use the following code:

var collection = database.GetCollection<Thingy>("db_Thingy");
Thingy tg= new Thingy();
tg.Foo = "Hello";
collection.insert(tg);
Share:
41,684
pm100
Author by

pm100

I was in SW from 1974 till 2019. Retired as CTO of SV based SW company that I cofounded. Started with cobol on punched cards. Ended with v large scale SAAS c# projects. And linux stuff in go. current fun project, writing PDP11 emulator in c++17. Cos why not -:) also writing a few bits in rust.

Updated on October 16, 2021

Comments

  • pm100
    pm100 over 2 years

    If I want to read and write mongo data with a POCO

    public class Thingy
    {
         public string Foo {get;set;}
    }
    ...
    coll.Insert(new Thing(Foo = "hello"));
    

    When I read back I get a failure saying that _id is an unexpected attribute (which it is). So then I added a field called _id to the class. Now the insert doesnt work saying that the _id field cannot be null. A tried BsonIgnoreIfNull attribute, that didnt work.

  • pm100
    pm100 almost 13 years
    thx - I have a feeling that there is a set of docs, samples or something that I am missing :-)
  • pm100
    pm100 almost 13 years
    @Bryan Migliorisi - this doesnt work. THe insert (or Save) fails telling me that Id cannot be null
  • pm100
    pm100 almost 13 years
    @Bryan Migliorisi - official c# driver from mongodb git site, downloaded yesterday
  • Robert Stam
    Robert Stam almost 13 years
    The data type of the Id property should be ObjectId, not BsonObjectId. Although BsonObjectId seems reasonable also, so I'll create JIRA request to support it as well.
  • Bryan Migliorisi
    Bryan Migliorisi almost 13 years
    Interesting... Robert, I've used BsonObjectId for every entity in my code without any problems using your driver.
  • pm100
    pm100 almost 13 years
    i had it as BsonObjectID - which explains it
  • Robert Stam
    Robert Stam almost 13 years
    As long as you assigned a value to the BsonObjectId everything was fine. It was only when you left it null and called Save expecting to autogenerate a unique value for it that there was a problem.
  • Robert Stam
    Robert Stam almost 13 years
    This JIRA has now been implemented: jira.mongodb.org/browse/CSHARP-231. I still recommend that you use ObjectId as the data type of your Id property, but if for some reason you prefer BsonObjectId it is now fully supported.
  • Bryan Migliorisi
    Bryan Migliorisi almost 13 years
    Does ObjectId automatically create a BsonObjectId value? I've been instantiating the object in my constructors.
  • Robert Stam
    Robert Stam almost 13 years
    There's some information about the difference between ObjectId and BsonObjectId at mongodb.org/display/DOCS/…. In general, if you are working with BsonDocuments you will be using BsonObjectIds, and if you are working with C# POCOs you will be using ObjectId (although since there is an automatic conversion from ObjectId to BsonObjectId you can also use ObjectIds with BsonDocuments).
  • s0nica
    s0nica over 11 years
    +1 for the final explanation that the _id can be set to any value of any data type (except array). I was a bit confused by the official documentation on this point
  • johnny g
    johnny g over 8 years
    [explitive] [explitive] [explitive], been fighting with this for 2 days. thanks @Chris Fulstow, such an obscure but key feature!
  • UpTheCreek
    UpTheCreek over 6 years
    That link seems to be broken now.
  • Chad Hedgcock
    Chad Hedgcock over 5 years
    Emphasis on The _id field doesn't have to be an MongoDB ObjectId. If you are using ObjectId or Bson attributes then your object is no longer POCO (plain old CLR object), so really, that's the answer. Avoid using them if you can.
  • Jepzen
    Jepzen over 5 years
    @ChadHedgcock i follow you here. But If i dont have any property on my poco class that corresponds to this I get an error while loading the document. like " _id couldt map to anything"
  • Chris Christopher
    Chris Christopher about 4 years
    @Jepzen bit late to game but the class attribute [BsonIgnoreExtraElements] might fix that issue.