5

我正在尝试使用以下代码将对象持久化到 MongoDB 中:

public class myClass
{
    public string Heading { get; set; }
    public string Body { get; set; } 
}

static void Main(string[] args)
{
    var mongo = MongoServer.Create();
    var db = mongo.GetDatabase("myDb");
    var col = db.GetCollection<BsonDocument>("myCollection");
    var myinstance = new myClass();
    col.Insert(myinstance);

    var query = Query.And(Query.EQ("_id", new ObjectId("4df06c23f0e7e51f087611f7)));
    var res = col.Find(query);
    foreach (var doc in res)
    {
        var obj = BsonSerializer.Deserialize<myClass>(doc);
    }
}

但是,尝试反序列化文档时出现以下异常“意外元素:_id”。

那么我需要以另一种方式反序列化吗?这样做的首选方法是什么?

TIA

索伦

4

3 回答 3

3

Projapati 的回答略有不同。首先,Mongo 会愉快地将 id 值反序列化为一个名为Idchsarp-ish 的属性。但是,如果您只是检索数据,则不一定需要这样做。

您可以添加[BsonIgnoreExtraElements]到您的课程中,它应该可以工作。这将允许您返回数据的子集,非常适合查询和视图模型。

于 2011-10-07T15:31:23.473 回答
3

您正在使用 ObjectId 搜索给定文档,但是当您保存 MyClass 的实例时,您没有提供 Id 属性,因此驱动程序将为您创建一个(您可以通过将 [BsonId] 属性添加到它),当您检索该文档时,您没有 Id,因此您会收到反序列化错误。

正如克里斯所说,您可以将 BsonIgnorExtraElements 属性添加到类中,但是您应该真正将 ObjectId 类型的 Id 属性添加到您的类中,您显然需要 Id(因为您在查询中使用它)。由于 _id 属性是为主键保留的,因此您只会检索一个文档,因此最好像这样编写查询:

col.FindOneById(new ObjectId("4df06c23f0e7e51f087611f7"));

检索文档后,您将反序列化为 MyClass 的实例这一事实有助于对集合进行强类型化,因此在创建集合的实例时,您可以执行此操作

var col = db.GetCollection<MyClass>("myCollection");

这样当您使用 FindOneById 方法检索文档时,驱动程序将负责反序列化,以便您将它们放在一起(假设您将 Id 属性添加到类中)您可以编写

var col = db.GetCollection<MyClass>("myCollection");
MyClass myClass = col.FindOneById(new ObjectId("4df06c23f0e7e51f087611f7"));

最后要注意的一件事,因为 _id 属性是在驱动程序保存时为您创建的,如果您将其从 MyClass 实例中删除,则每次保存该文档时,您都会获得一个新的 Id 并因此获得一个新的文档,所以如果您将其保存 n 次,您将拥有 n 个文档,这可能不是您想要的。

于 2011-11-23T21:41:54.773 回答
0

尝试将 _id 添加到您的班级。当您的班级没有文档中所有字段的成员时,通常会发生这种情况。

public class myClass
{
    public ObjectId _id { get; set; }
    public string Heading { get; set; }
    public string Body { get; set; } 
}
于 2011-07-06T00:28:04.000 回答