添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Learn more about Collectives

Teams

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Learn more about Teams

I am new to using mongo db in C# , but I am trying to import large database in mongo db. MyDb consists entities having only simple parameters Id , Body , Title Tags.

This is example of entity in mongo.

"Id" : "someff asdsa", "Title" : "fsfds fds", "Body ": "fsdfsd fs", "Tags" : "fsdfdsfsd"

This is my class of mongoEntity in C#

 [BsonIgnoreExtraElements]
    class Element
        [BsonId]
        public ObjectId _id { get; set; }
        [BsonElement("Id")]
        public string Id { get; set; }
        [BsonElement("Title")]
        public string Title { get; set; }
        [BsonElement("Body")]
        public string Body { get; set; }
        [BsonElement("Tags")]
        public string Tags { get; set; }
        public void ShowOnConsole()
            Console.WriteLine(" _id {0} Id {1} Title {2} Body {3} Tags {4} ", _id, Id, Title, Body, Tags);

This is my code in Main method

  const string connectionString = "mongodb://localhost";
            var client = new MongoClient(connectionString);
            MongoServer server = client.GetServer();
            MongoDatabase database = server.GetDatabase("mydb");
            MongoCollection<Element> collection = database.GetCollection<Element>("train");
            Console.WriteLine("Zaimportowano {0} rekordow ", collection.Count());
            MongoCursor<Element> ids = collection.FindAll();   
             foreach (Element entity in ids)
                 entity.ShowOnConsole();

When i run this code I am able to see some data, but I'v got exception "Cannot deserialize string from BsonType Int32." I think that one of property is represented in database as int , but I dont know how to deal with it ? How come one property in one entity is int and the same property in another object is string ? What I have to do to read all database ?

Yes, String property in C# object has Int32 value in mongo storage, so you have exception during serialization (see code for MongoDB.Bson.Serialization.Serializers.BsonStringSerializer class).

1) You can define your own serializer, which will deserialize Int32 values to string property as well as String ones. Here it is:

public sealed class StringOrInt32Serializer : BsonBaseSerializer
    public override object Deserialize(BsonReader bsonReader, Type nominalType,
        Type actualType, IBsonSerializationOptions options)
        var bsonType = bsonReader.CurrentBsonType;
        switch (bsonType)
            case BsonType.Null:
                bsonReader.ReadNull();
                return null;
            case BsonType.String:
                return bsonReader.ReadString();
            case BsonType.Int32:
                return bsonReader.ReadInt32().ToString(CultureInfo.InvariantCulture);
            default:
                var message = string.Format("Cannot deserialize BsonString or BsonInt32 from BsonType {0}.", bsonType);
                throw new BsonSerializationException(message);
    public override void Serialize(BsonWriter bsonWriter, Type nominalType,
        object value, IBsonSerializationOptions options)
        if (value != null)
            bsonWriter.WriteString(value.ToString());
            bsonWriter.WriteNull();

Then mark necessary properties (which have different types in MongoDB in your opinion) with this serializer, for example:

[BsonElement("Body")]
[BsonSerializer(typeof(StringOrInt32Serializer))]
public string Body { get; set; }

Also I've found very similar question here: Deserializing field when type is changed using MongoDb csharp driver

2) The second approach - is to 'normalize' your data in storage: convert all integer field values to string. So, you should change field $type from 16 (32-bit integer) to 2 (string). See BSON types. Let's do it for body field:

db.train.find({ 'body' : { $type : 16 } }).forEach(function (element) {   
  element.body = "" + element.body;  // Convert field to string
  db.train.save(element);
                Hi. The first method doesn't work anymore as the BsonBaseSerializer class is no longer a part of sdk.
– It's a trap
                Mar 31, 2017 at 9:08

I tried the above example but looks like some class structures have changed. I have a JSON field called BuildingNumber which has number most of the time but in case of Flats or Cottages its left blank. Code is below which is working as expected

public class BsonStringNumericSerializer : SerializerBase<string>
    public override string Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args)
        var bsonType = context.Reader.CurrentBsonType;
        switch (bsonType)
            case BsonType.Null:
                context.Reader.ReadNull();
                return null;
            case BsonType.String:
                return context.Reader.ReadString();
            case BsonType.Int32:
                return context.Reader.ReadInt32().ToString(CultureInfo.InvariantCulture);
            default:
                var message = string.Format($"Custom Cannot deserialize BsonString or BsonInt32 from BsonType {bsonType}");
                throw new BsonSerializationException(message);
    public override void Serialize(BsonSerializationContext context, BsonSerializationArgs args, string value)
        if (value != null)
            if (int.TryParse(value, out var result))
                context.Writer.WriteInt32(result);
                context.Writer.WriteString(value);
            context.Writer.WriteNull();
[BsonElement("BUILDING_NUMBER")]
[BsonSerializer(typeof(BsonStringNumericSerializer))]
public string BuildingNumberString { get; set; }

This will work in C# Mongo 2.0+

public class TestingObjectTypeSerializer : IBsonSerializer
    public Type ValueType { get; } = typeof(string);
    public object Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args)
        if (context.Reader.CurrentBsonType == BsonType.Int32) return GetNumberValue(context);
        return context.Reader.ReadString();
    public void Serialize(BsonSerializationContext context, BsonSerializationArgs args, object value)
        context.Writer.WriteString(value as string);
    private static object GetNumberValue(BsonDeserializationContext context)
        var value = context.Reader.ReadInt32();
        switch (value)
            case 1:
                return "one";
            case 2:
                return "two";
            case 3:
                return "three";
            default:
                return "BadType";

And you can use it like

public class TestingObject
    public string FirstName { get; set; }
    public string LastName { get; set; }
    [BsonSerializer(typeof(TestingObjectTypeSerializer))]
    public string TestingObjectType { get; set; }

Theoretically you can change strings to objects then you'll be able to deserialize int as well as string. So if you have

Tags as int in DB, this construction will deserialize it and then you can convert it as you wish.

[BsonElement("Tags")]
public object Tags { get; set; }
        

Thanks for contributing an answer to Stack Overflow!

  • Please be sure to answer the question. Provide details and share your research!

But avoid

  • Asking for help, clarification, or responding to other answers.
  • Making statements based on opinion; back them up with references or personal experience.

To learn more, see our tips on writing great answers.