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 ?
Welcome to the documentation site for the official MongoDB C++ driver. You can add the driver to your application to work with MongoDB using the C++11 or later standard.
By developing with C# and MongoDB together one opens up a world of possibilities. Console, window, and web applications are all possible. As are cross-platform mobile applications using the Xamarin framework.
The official MongoDB Node. js driver allows Node. js applications to connect to MongoDB and work with data. The driver features an asynchronous API which allows you to interact with MongoDB using Promises or via traditional callbacks.
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);
}
else
{
context.Writer.WriteString(value);
}
}
else
{
context.Writer.WriteNull();
}
}
}
[BsonElement("BUILDING_NUMBER")]
[BsonSerializer(typeof(BsonStringNumericSerializer))]
public string BuildingNumberString { get; set; }
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());
}
else
{
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);
});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With