【问题标题】:Can't deserialize from ObjectId to String in a MongoDb collection query无法在 MongoDb 集合查询中从 ObjectId 反序列化为 String
【发布时间】:2019-03-29 10:03:28
【问题描述】:

每当我尝试从集合中获取 Id 列表时:

var messages = db.GetCollection<MessageExchange>(collectionName);
var ids = messages
   .AsQueryable()
   .Where(_=> true)
   .Select(x => x.Id)
   .ToList();

我收到一个转换错误:

System.FormatException HResult=0x80131537 消息=不能 从 BsonType 'ObjectId' 反序列化一个 'String'。来源= StackTrace:

我无法修改类的定义,因为它在我无法更改的包中实现。因此放置的解决方案:

[BsonRepresentation(BsonType.ObjectId)] 

关于它,不可能。基于this

是否可以在 Linq 查询中强制转换?

【问题讨论】:

  • 您想要字符串列表还是对象 ID 列表?
  • 只需要一个id列表,如果是字符串就更好了

标签: c# mongodb casting mongodb-.net-driver


【解决方案1】:

不,因为db.GetCollection&lt;MessageExchange&gt; 将集合定义为强类型对象,驱动程序将结合执行的任何进一步逻辑(使用 linq 或其他方式)来处理这些对象。

您最好的选择是:

  1. 在您自己的代码中定义一个与您的 Mongo Collection 兼容的类,然后使用该类反序列化您的结果db.GetCollection&lt;MyCustomMessageExchange&gt;,然后您可以将其与上面的 linq 查询一起使用以仅选择 id。

  2. 只需使用默认的BsonDocument 来定义您的集合并使用投影: db.GetCollection&lt;BsonDocument&gt;.Find(new BsonDocument()).Project("{_id: 1}").ToList()

【讨论】:

  • 我喜欢选项 2!没想到。这将导致代码库中的开销最少。
  • @cl0ud - 选项 2 已更新,我忘记包含 .Find()
  • 我刚刚用这段代码实现了它:var myIds = db .GetCollection&lt;BsonDocument&gt;(collectionName) .Find(_ =&gt; true) .Project(Builders&lt;BsonDocument&gt;.Projection.Include("_id")) .ToList(); 这正在工作并创建这样的元素:{{ "_id" : "cc969282-c9d2-4cba-a776-d79ff1274d56" }}
【解决方案2】:

您绝不一定要使用包中的内容 - 如果您知道类的定义是什么,我建议您在项目中滚动您自己的 MessageExchange 并使用它来使用驱动程序查询集合。

这还允许您仅获取您需要的字段(在您的新类上使用 [BsonIgnoreExtraElements] 属性),而不是包的作者强加给您的内容。

如果使用类型 MessageExchange 对于您的程序流程和结构是绝对必要的,我建议使用 AutoMapper 之类的东西从您自己的类型转换回原始类型。

【讨论】:

  • 能否详细说明automapper的使用?
  • @DanielV automapper 允许您在两个模型之间创建关系。所以你不必做凌乱的new MessageExchange() 并手动分配属性。你可以简单地做var messageExchange = mapper.Map&lt;MessageExchange&gt;(yourNewMessageExchangeObject);
  • 我明白,我正在探索@steveland 方法来实现完全独立的东西,因为我需要的是“ids”实际上并不关心对象
  • @DanielV 我肯定会选择史蒂夫回答的选项 2!
【解决方案3】:

ObjectId structure 实现了一个ToString 方法,允许您将对象转换为其字符串表示形式。

所以我认为你可以这样做:

var messages = db.GetCollection<MessageExchange>(collectionName);
var ids = messages
   .AsQueryable()
   .Where(_=> true)
   .Select(x => x.Id.ToString())
   .ToList();

【讨论】:

  • 史蒂夫的方法似乎是正确的,谢谢您的回复。
猜你喜欢
  • 1970-01-01
  • 2015-01-08
  • 2012-01-14
  • 1970-01-01
  • 1970-01-01
  • 2013-01-17
  • 1970-01-01
  • 2017-06-25
  • 1970-01-01
相关资源
最近更新 更多