52

I got the result from the collection in MongoDB, the structure is the same as below

[DataContract]
public class Father
{
    [BsonId]
    [DataMember]
    public MongoDB.Bson.ObjectId _id { get; set; }

    [DataMember]
    public string Id { get; set; }

    [DataMember]
    public List<Child> childs { get; set; }
}

[DataContract]
public class Child
{
    [DataMember]
    public string Id { get; set; }

    [DataMember]
    public int Name { get; set; }
}

When I try this:

List<Father> f = result.ToList();

It calls Element 'Id' does not match any field or property of the class Model.Child

I think it just takes 'Id' as something else.

How can I deal with it? Thank you

Ratan Uday Kumar
  • 5,738
  • 6
  • 35
  • 54
EasonBlack
  • 4,196
  • 4
  • 21
  • 24
  • 1
    Can you give a more complete listing of the code that is causing this exception? For instance, what is results? Also, can you show us what the documents look like in the database (preferably in json format). – Craig Wilson Jul 20 '12 at 13:21
  • 2
    I solved this problem by add a _id in the sub class as I did in the main class. I guess, all the ducument needs an 'id'.And if I don't define one , the system will think there is a '_id' in the class. That makes me couldn't transfer the document to `List`. – EasonBlack Aug 01 '12 at 09:17
  • 1
    Check out the serialization options http://www.mongodb.org/display/DOCS/CSharp+Driver+Serialization+Tutorial - you can mark whatever property to be the id, it doesn't have to be '_id' for example – Alex Nov 13 '12 at 11:23
  • May be related to this - https://stackoverflow.com/questions/23448634/mongodb-c-sharp-driver-ignore-fields-on-binding . – Victor Yarema Feb 18 '19 at 17:37

9 Answers9

101

You can resolve the issue by adding [BsonIgnoreExtraElements] on top of the class declaration. ObjectId is internally maintained by MongoDB which may not be needed unless you want to get additional information such as timestamp from the object. Hope this helps.

Liam
  • 27,717
  • 28
  • 128
  • 190
Naga
  • 2,368
  • 3
  • 23
  • 33
12
var conventionPack = new ConventionPack { new IgnoreExtraElementsConvention(true) };
        ConventionRegistry.Register("IgnoreExtraElements", conventionPack, type => true);

This works just perfectly! [BsonIgnoreExtraElements] also worked well, but, if you want to add any other ConventionRegistry like CamelCaseElementNameConvention, then, it overrides the Attribute one and the same exception occurs. Not sure if that could also be achieved using some other attribute.

6

I was using a dynamic list (List) to build a filter and was receiving a similar error. I added these lines to my data class to fix the problem.

[BsonId]
public ObjectId Id { get; set; }
Tom Glenn
  • 81
  • 1
  • 3
5

this work for my case: add the attribute

    [DataMember]
    [BsonElement("songName")]

onto the elements:

[BsonIgnoreExtraElements]
public class Music
{
   
    [BsonId]
    [DataMember]
    public MongoDB.Bson.ObjectId _id { get; set; }
    [DataMember]
    public string Id { get; set; }

    [DataMember]
    [BsonElement("songName")]
    public string SongName { get; set; }

    [DataMember]
    [BsonElement("artistName")]
    public string ArtistName { get; set; }}
Liam
  • 27,717
  • 28
  • 128
  • 190
Yook Feng
  • 59
  • 1
  • 1
3

I faced to same problem.Same error occured at var data = query.ToList();

       var collection = db.GetCollection<Product>("Products");

        var query =
            from e in collection.AsQueryable<Product>()
            where e.name == "kalem"
            select e;

        var data = query.ToList();

and my insert was this:

    var collection = db.GetCollection<Product>("Products");

    collection.InsertBatch(products);

I solved as below.

        ObjectId id = new ObjectId();
        var collection = db.GetCollection<Product>("Products");

        collection.InsertBatch(products);
        id = pr.Id;

and I added id to Product class as below Product Class

class Product
{
    public ObjectId Id { get; set; }
    public string name { get; set; }
    public string category { get; set; }
    public double price { get; set; }
    public DateTime enterTime { get; set; }
}
Mehmet Topçu
  • 1
  • 1
  • 16
  • 31
2

you can use BsonNoId attribute

[DataContract]
[BsonNoId]
public class Child
{
  [DataMember]
  public string Id { get; set; }

  [DataMember]
  public int Name { get; set; }
}
0

just add this in the top of the class [BsonIgnoreExtraElements]

-1

all you have to do is removing the [DataMember] on the ObjecId attribute and bind the Id to the ObjectId _id.

so your class should look like this :

[DataContract]
public class Father
{
    [BsonId]
    public MongoDB.Bson.ObjectId _id { get; set; }

    [DataMember]
    public string Id { 
          get { return _id.ToString(); }
          set { _id = ObjectId.Parse(value); }
    }

    [DataMember]
    public List<Child> childs { get; set; }
}

ps : in your case the child id must be generated manually, if you want it to be an objectId(mongo), you will have do the same trick finally, to deserialized the object, you should use the newtonsoft.json reference and do like this

Father = JsonConvert.DeserializeObject<Father>(response.Content); 
  • This actually does not work - The ObjectId.Parse(value) always returns 0's to the _id field. Better to just store this as a string IMHO – AutomationNation Aug 23 '16 at 23:33
-2

Your Child class should probably specify it inherits Father

public class Child: Father { ... }

Your Father class should probably add known type attribute (for WCF ).

[DataContract]
[KnownType(typeof(Child))]
public class Father

If this is a MongoCollection("fathers") that you save / fetch through, then you may need to register a class map for each expected child type.

if (!BsonClassMap.IsClassMapRegistered(typeof(Child)))
{
    BsonClassMap.RegisterClassMap<Child>(
        cm => { cm.AutoMap(); });
}

As @alexjamesbrown mentioned, you are not required to name the id field on your poco object '_id'. The idea with inheritance is to inherit. So using the Father's "id" field (whatever it is named) should suffice. It's not clear why your Father class has both Id and _id properties. One of them is probably not necessary.

Nuk Nuk San
  • 550
  • 3
  • 5
  • You don't need to use inheritance. I have also come across this problem. I don't know what it is yet, but I don't think it inheritance will solve it. I similar, working code, elsewhere. – Daryn May 28 '14 at 21:02
  • This got me closer: http://stackoverflow.com/questions/13859295/strange-behavior-of-mongodb-linq-provider-for-fields-called-id. I eventually renamed my field to something containing more than just id or _id, both in the pocp and mongo projection. That did the trick – Daryn May 28 '14 at 21:11