将POCO与mongodb c#驱动程序一起使用时如何管理_id字段

Posted

技术标签:

【中文标题】将POCO与mongodb c#驱动程序一起使用时如何管理_id字段【英文标题】:how to manage _id field when using POCO with mongodb c# driver 【发布时间】:2011-08-29 03:00:25 【问题描述】:

如果我想用 POCO 读写 mongo 数据

public class Thingy

     public string Foo get;set;

...
coll.Insert(new Thing(Foo = "hello"));

当我回读时,我收到一个失败消息,说 _id 是一个意外属性(确实如此)。因此,我在类中添加了一个名为 _id 的字段。现在插入不起作用,说 _id 字段不能为空。一个尝试过的 BsonIgnoreIfNull 属性,它不起作用。

【问题讨论】:

【参考方案1】:

如下添加属性:

public BsonObjectId Id  get; set; 

MongoDB 驱动程序在序列化\反序列化过程中自动将Id 转换为_id

【讨论】:

thx - 我感觉有一组文档、示例或我缺少的东西:-) @Bryan Migliorisi - 这不起作用。插入(或保存)失败告诉我 Id 不能为空 @Bryan Migliorisi - 来自 mongodb git 站点的官方 c# 驱动程序,昨天下载 Id属性的数据类型应该是ObjectId,而不是BsonObjectId。虽然 BsonObjectId 看起来也很合理,所以我也会创建 JIRA 请求来支持它。 有趣...罗伯特,我已经为代码中的每个实体使用了 BsonObjectId,使用您的驱动程序没有任何问题。【参考方案2】:

当您插入一个对象时,如果它没有 _id 字段,则驱动程序会添加一个并将其设置为 12 字节的 MongoDB ObjectId 值。

您只需将Id 属性添加到您的POCO,它将从_id 反序列化:

public class Thingy

     public ObjectId Id  get; set; 

或者,如果您想委托另一个属性映射到_id,那么您可以使用BsonIdAttribute 来装饰它,如下所示:

[BsonId]
public ObjectId MyKey  get; set;    

_id 字段不必是 MongoDB ObjectId,您可以将其设置为任何数据类型(数组除外)的任何值,它只需要在集合中是唯一的即可。

【讨论】:

+1 最终解释 _id 可以设置为任何数据类型的任何值(数组除外)。关于这一点的官方文档让我有点困惑 [explitive] [explitive] [explitive],已经为此奋斗了 2 天。感谢@Chris Fulstow,这是一个不起眼但很关键的功能! 强调_id 字段不必是 MongoDB ObjectId。如果您使用 ObjectId 或 Bson 属性,那么您的对象不再是 POCO(普通的旧 CLR 对象),这就是答案。尽可能避免使用它们。 @ChadHedgcock 我跟着你。但是,如果我的 poco 类上没有与此相对应的任何属性,则在加载文档时会出现错误。比如“_id 不能映射到任何东西” @Jepzen 有点晚了,但类属性 [BsonIgnoreExtraElements] 可能会解决这个问题。【参考方案3】:

您必须为 id 添加一个属性(或字段)并告诉序列化程序您要使用哪个 id 生成器。

[BsonId(IdGenerator = typeof(ObjectIdGenerator))]
public object ThingyId  get; set; 

MongoDb 驱动程序中有 3 个可用,您也可以自己编写。更多信息http://www.mongodb.org/display/DOCS/CSharp+Driver+Serialization+Tutorial#CSharpDriverSerializationTutorial-WriteacustomIdgenerator

【讨论】:

那个链接现在好像坏了。【参考方案4】:
public class Thingy

      public ObjectId Id  get; set; 
      public string Foo  get; set; 

按类别

如果需要,请使用以下代码:

var collection = database.GetCollection<Thingy>("db_Thingy");
Thingy tg= new Thingy();
tg.Foo = "Hello";
collection.insert(tg);

【讨论】:

【参考方案5】:

我一般都把Thingy包起来:

public class MongoThingy

    public ObjectId Id  get; set; 
    public Thingy Thingy  get; set; 

这让它变得容易多了,因为很多时候,Thingy 类来自另一个我无法控制的库。反序列化也更容易,以便将其交给其他人进行处理。

【讨论】:

【参考方案6】:

https://docs.microsoft.com/pt-br/aspnet/core/tutorials/first-mongo-app?view=aspnetcore-5.0&tabs=visual-studio的路

using MongoDB.Bson;
using MongoDB.Bson.Serialization.Attributes;

namespace BooksApi.Models

    public class Book
    
        [BsonId]
        [BsonRepresentation(BsonType.ObjectId)]
        public string Id  get; set; 

        [BsonElement("Name")]
        public string BookName  get; set; 

        (...)
    

【讨论】:

以上是关于将POCO与mongodb c#驱动程序一起使用时如何管理_id字段的主要内容,如果未能解决你的问题,请参考以下文章

MongoDB C# 驱动程序:在插入时忽略属性

MongoDB - 使用 C# 驱动程序按日期和时间搜索

将 WCF 服务与实体框架 4 和...DTO 一起使用?

在mono中使用c#驱动程序比较mongo集合的两个字段

POCO 生成工具

如何将 maxPoolSize 与 mongodb-php 驱动程序版本 1.2.0 一起使用