![](/img/trans.png)
[英]C# Mongo Driver error: Cannot deserialize a 'Int32' from BsonType 'Document'
[英]mongodb C# exception Cannot deserialize string from BsonType Int32
我是在 C# 中使用 mongo db 的新手,但我正在尝试在 mongo db 中导入大型数据库。 MyDb 由仅具有简单参数 Id 、 Body 、 Title Tags 的实体组成。
这是 mongo 中的实体示例。
{
"Id" : "someff asdsa",
"Title" : "fsfds fds",
"Body ": "fsdfsd fs",
"Tags" : "fsdfdsfsd"
}
这是我在 C# 中的 mongoEntity 类
[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);
}
}
这是我在 Main 方法中的代码
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();
}
当我运行此代码时,我能够看到一些数据,但出现异常“无法从 BsonType Int32 反序列化字符串”。 我认为其中一个属性在数据库中表示为 int ,但我不知道如何处理它? 为什么一个实体中的一个属性是 int 而另一个对象中的相同属性是 string ? 我必须做什么才能读取所有数据库?
是的,C#对象中的String
属性在mongo存储中具有Int32
值,因此在序列化期间您有异常(请参阅MongoDB.Bson.Serialization.Serializers.BsonStringSerializer
类的代码)。
1)您可以定义自己的序列化,这将反序列化Int32
值字符串属性以及String
的。 这里是:
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();
}
}
}
然后使用此序列化程序标记必要的属性(在您看来MongoDB中具有不同的类型),例如:
[BsonElement("Body")]
[BsonSerializer(typeof(StringOrInt32Serializer))]
public string Body { get; set; }
此外,我在这里发现了非常相似的问题: 使用MongoDb csharp驱动程序更改类型时反序列化字段
2)第二种方法 - 在存储中“标准化”您的数据:将所有整数字段值转换为字符串。 因此,您应该将字段$type
从16(32位整数)更改为2(字符串)。 见BSON类型 。 让我们为body
领域做:
db.train.find({ 'body' : { $type : 16 } }).forEach(function (element) {
element.body = "" + element.body; // Convert field to string
db.train.save(element);
});
这将适用于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";
}
}
}
你可以像使用它一样
public class TestingObject
{
public string FirstName { get; set; }
public string LastName { get; set; }
[BsonSerializer(typeof(TestingObjectTypeSerializer))]
public string TestingObjectType { get; set; }
}
我尝试了上面的例子,但看起来有些类结构已经改变了。 我有一个名为BuildingNumber的JSON字段,其中大部分时间都有数字,但在Flats或Cottages的情况下,它留空。 代码低于其正常工作
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; }
从理论上讲,您可以将字符串更改为对象,然后您就可以反序列化 int 以及字符串。 所以如果你有
在 DB 中标记为 int,此构造将对其进行反序列化,然后您可以根据需要对其进行转换。
[BsonElement("Tags")]
public object Tags { get; set; }
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.