热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

C#中如何将MongoDB->RunCommand结果映射到业务类的方法总结

这篇文章主要给大家总结介绍了关于C#中如何将MongoDB->RunCommand结果映射到业务类的方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面来一起看看吧。

前言

一直没实际用过MongoDB,最近有个项目中用了用,踩了一些坑。这篇文章会介绍将MongoDB->RunCommand结果映射到业务类时碰到的问题,以及对各种方法的探索。

Collection中的数据是这样的:

使用find命令查询数据:

db.runCommand({"find":"test", limit:2, sort:{AddTime:-1}})

查询返回的数据结构是这样的,需要的数据在firstBatch中:

{
 "cursor" : {
 "firstBatch" : [ 
  {
  "_id" : ObjectId("5ad0042944fd3929db6b869f"),
  "Name" : "李四",
  "AddTime" : ISODate("2018-04-12T01:13:18.965Z")
  }, 
  {
  "_id" : ObjectId("5ad003e844fd3929db6b869e"),
  "Name" : "张三",
  "AddTime" : ISODate("2018-04-02T01:11:18.965Z")
  }
 ],
 "id" : NumberLong(0),
 "ns" : "test.test"
 },
 "ok" : 1.0
}

下面将在C#中运行find命令来执行查询,并将结果映射到自定义的PersonInfo类。

 private class PersonInfo
 {
  public string Id { get; set; }
  public string Name { get; set; }
  public DateTime AddTime { get; set; }
 }

需要注意PersonInfo中的属性Id和Document中的名称_id有些不一样,需要进行映射。因为不同的反序列化方法,采用的方式也会不同,所以下面会有相关介绍。

使用Json.NET

因为Json.NET用的比较多,基本思路就是用它来反序列化Bson,但是Json和Bson是不同的,不能用JsonConvert。

不过Json.NET提供了一个新的包Newtonsoft.Json.Bson来解析Bson数据,并且提供了一个例子。

https://www.newtonsoft.com/json/help/html/DeserializeFromBson.htm

这个例子有点过时了,里边用的BsonReader我已替换为BsonDataReader。

byte[] data = Convert.FromBase64String("MQAAAAJOYW1lAA8AAABNb3ZpZSBQcmVtaWVyZQAJU3RhcnREYXRlAMDgKWE8AQAAAA==");
MemoryStream ms = new MemoryStream(data);
using (BsonDataReader reader = new BsonDataReader(ms))
{
 JsonSerializer serializer = new JsonSerializer();
 
 Event e = serializer.Deserialize(reader);
 
 Console.WriteLine(e.Name);
 // Movie Premiere
}

看样子有个byte数组就可以了,然后再看BsonDocument正好有个方法ToBson,获取到的就是byte[]。

思路:先将RunCommand的结果映射为BsonDocument,然后查找到firstBatch,然后将其ToBson,然后使用Newtonsoft.Json.Bson反序列化。

一切看起来很easy!

马上码起来:

  var findCommand = BsonDocument.Parse("{\"find\":\"test\", limit:2, sort:{AddTime:-1}}");
  var findResult = database.RunCommand(findCommand)
  .GetElement("cursor").Value.ToBsonDocument()
  .GetElement("firstBatch").ToBsonDocument()
  .ToBson();
  var persOnList= DeserializeBson(findResult);

数组不能是Bson的根元素,所以这里定义了一个PersonList类:

 private class PersonList
 {
  public string Name { get; set; }
  [JsonProperty(PropertyName = "Value")]
  public PersonInfo[] List { get; set; }
 }

需要注意的是上边代码中 GetElement(“firstBatch”).ToBsonDocument() 返回的数据格式是这样的:

这里用了JsonProperty将Value映射为List。

还有Person类中的属性名称和document中的也有不同,也需要映射:

 private class PersonInfo
 {
  [JsonProperty(PropertyName = "_id")]
  [JsonConverter(typeof(ObjectIdConverter))]
  public string Id { get; set; }
  public string Name { get; set; }
  public DateTime AddTime { get; set; }
 }

这里还用了一个 JsonConverter(typeof(ObjectIdConverter)) ,因为ObjectId不能直接转换为string,所以定义了一个ObjectIdConverter类:

 public class ObjectIdConverter : JsonConverter
 {
  public override bool CanConvert(Type objectType)
  {
   return objectType == typeof(ObjectId);
  }
 
  public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
  {
   if (reader.Value != null)
   {
    var value = (byte[])reader.Value;
 
    var result = BitConverter.ToString(value).Replace("-", string.Empty).ToLowerInvariant();
 
    return result;
   }
 
   return string.Empty;
  }
 
  public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
  {
   throw new NotImplementedException();
  }
 }

还有一个重要的方法,反序列化:

  public static T DeserializeBson(byte[] data)
  {
   MemoryStream ms = new MemoryStream(data);
   using (BsonDataReader reader = new BsonDataReader(ms, false, DateTimeKind.Local))
   {
    JsonSerializer serializer = new JsonSerializer();
 
    T e = serializer.Deserialize(reader);
    return e;
   }
  }

现在运行程序看看吧:

但是感觉好复杂,过了一弯又一弯。

使用MongoDB .NET Driver内置

话说这么常用的功能,SDK应该内置了才对,何必舍近求远,。

既然RunCommand可以传递一个类型,那么SDK应该是支持反序列化自定义类型的。

尝试根据返回的结果定义一个新的类:

  [BsonIgnoreExtraElements]
  private class FindCommandResult
  {
   [BsonElement("cursor")]
   public ResultCursor Cursor { get; set; }
  }
 
  [BsonIgnoreExtraElements]
  private class ResultCursor
  {
   [BsonElement("firstBatch")]
   public PersonInfo[] Batch { get; set; }
  }
 
  private class PersonInfo
  {
   [BsonId]
   [BsonRepresentation(BsonType.ObjectId)]
   public string Id { get; set; }
   public string Name { get; set; }
   public DateTime AddTime { get; set; }
  }

BsonIgnoreExtraElements、BsonElement、BsonId、BsonRepresentation这些都是SDK内置的Attribute,相关作用大家应该能够一目了然。

再看看查询这块的代码:

   var findCommand = BsonDocument.Parse("{\"find\":\"test\", limit:1, sort:{AddTime:-1}}");
   var findResult = database.RunCommand(findCommand);

代码跑起来:

这个方式相比Json.NET更直接,更简单。

使用查找赋值的方式

为了反序列化,适应MongoDB,定义了一些没有业务意义的类型,加了很多的属性注解,感觉还不够直接显性。

也许只需要数据中的某几个字段,或者根本就没必要定义类型,只需要放到一个列表中。

又查看了BsonDocument的定义,发现可以在运行命令时先反序列化为BsonDocument,然后再根据返回的数据结构使用GetElement获取相关字段的值。

代码如下:

   var findCommand = BsonDocument.Parse("{\"find\":\"test\", limit:2, sort:{AddTime:-1}}");
   var findResult = database.RunCommand(findCommand)
    .GetElement("cursor").Value.ToBsonDocument()
    .GetElement("firstBatch").Value.AsBsonArray.Select(d =>
    {
     var dbd = d.AsBsonDocument;
     return new PersonInfo()
     {
      Id = dbd.GetElement("_id").Value.AsObjectId.ToString(),
      AddTime = dbd.GetElement("AddTime").Value.ToLocalTime(),
      Name = dbd.GetElement("Name").Value.ToString(),
     };
    }).ToList();

运行后直接返回List ,更贴近业务需求。

这是本文中最简单的方式了。

如果做的更通用点,可以在这里通过反射自动实例化相关类型,不过这不如直接使用SDK内置的反序列化方式了。

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对的支持。


推荐阅读
  • 本文介绍了在开发Android新闻App时,搭建本地服务器的步骤。通过使用XAMPP软件,可以一键式搭建起开发环境,包括Apache、MySQL、PHP、PERL。在本地服务器上新建数据库和表,并设置相应的属性。最后,给出了创建new表的SQL语句。这个教程适合初学者参考。 ... [详细]
  • 本文是一位90后程序员分享的职业发展经验,从年薪3w到30w的薪资增长过程。文章回顾了自己的青春时光,包括与朋友一起玩DOTA的回忆,并附上了一段纪念DOTA青春的视频链接。作者还提到了一些与程序员相关的名词和团队,如Pis、蛛丝马迹、B神、LGD、EHOME等。通过分享自己的经验,作者希望能够给其他程序员提供一些职业发展的思路和启示。 ... [详细]
  • 使用在线工具jsonschema2pojo根据json生成java对象
    本文介绍了使用在线工具jsonschema2pojo根据json生成java对象的方法。通过该工具,用户只需将json字符串复制到输入框中,即可自动将其转换成java对象。该工具还能解析列表式的json数据,并将嵌套在内层的对象也解析出来。本文以请求github的api为例,展示了使用该工具的步骤和效果。 ... [详细]
  • 解决VS写C#项目导入MySQL数据源报错“You have a usable connection already”问题的正确方法
    本文介绍了在VS写C#项目导入MySQL数据源时出现报错“You have a usable connection already”的问题,并给出了正确的解决方法。详细描述了问题的出现情况和报错信息,并提供了解决该问题的步骤和注意事项。 ... [详细]
  • 使用正则表达式爬取36Kr网站首页新闻的操作步骤和代码示例
    本文介绍了使用正则表达式来爬取36Kr网站首页所有新闻的操作步骤和代码示例。通过访问网站、查找关键词、编写代码等步骤,可以获取到网站首页的新闻数据。代码示例使用Python编写,并使用正则表达式来提取所需的数据。详细的操作步骤和代码示例可以参考本文内容。 ... [详细]
  • EPICS Archiver Appliance存储waveform记录的尝试及资源需求分析
    本文介绍了EPICS Archiver Appliance存储waveform记录的尝试过程,并分析了其所需的资源容量。通过解决错误提示和调整内存大小,成功存储了波形数据。然后,讨论了储存环逐束团信号的意义,以及通过记录多圈的束团信号进行参数分析的可能性。波形数据的存储需求巨大,每天需要近250G,一年需要90T。然而,储存环逐束团信号具有重要意义,可以揭示出每个束团的纵向振荡频率和模式。 ... [详细]
  • 目录实现效果:实现环境实现方法一:基本思路主要代码JavaScript代码总结方法二主要代码总结方法三基本思路主要代码JavaScriptHTML总结实 ... [详细]
  • 本文介绍了九度OnlineJudge中的1002题目“Grading”的解决方法。该题目要求设计一个公平的评分过程,将每个考题分配给3个独立的专家,如果他们的评分不一致,则需要请一位裁判做出最终决定。文章详细描述了评分规则,并给出了解决该问题的程序。 ... [详细]
  • 禁止程序接收鼠标事件的工具_VNC Viewer for Mac(远程桌面工具)免费版
    VNCViewerforMac是一款运行在Mac平台上的远程桌面工具,vncviewermac版可以帮助您使用Mac的键盘和鼠标来控制远程计算机,操作简 ... [详细]
  • 本文介绍了C#中数据集DataSet对象的使用及相关方法详解,包括DataSet对象的概述、与数据关系对象的互联、Rows集合和Columns集合的组成,以及DataSet对象常用的方法之一——Merge方法的使用。通过本文的阅读,读者可以了解到DataSet对象在C#中的重要性和使用方法。 ... [详细]
  • t-io 2.0.0发布-法网天眼第一版的回顾和更新说明
    本文回顾了t-io 1.x版本的工程结构和性能数据,并介绍了t-io在码云上的成绩和用户反馈。同时,还提到了@openSeLi同学发布的t-io 30W长连接并发压力测试报告。最后,详细介绍了t-io 2.0.0版本的更新内容,包括更简洁的使用方式和内置的httpsession功能。 ... [详细]
  • switch语句的一些用法及注意事项
    本文介绍了使用switch语句时的一些用法和注意事项,包括如何实现"fall through"、default语句的作用、在case语句中定义变量时可能出现的问题以及解决方法。同时也提到了C#严格控制switch分支不允许贯穿的规定。通过本文的介绍,读者可以更好地理解和使用switch语句。 ... [详细]
  • 闭包一直是Java社区中争论不断的话题,很多语言都支持闭包这个语言特性,闭包定义了一个依赖于外部环境的自由变量的函数,这个函数能够访问外部环境的变量。本文以JavaScript的一个闭包为例,介绍了闭包的定义和特性。 ... [详细]
  • ASP.NET2.0数据教程之十四:使用FormView的模板
    本文介绍了在ASP.NET 2.0中使用FormView控件来实现自定义的显示外观,与GridView和DetailsView不同,FormView使用模板来呈现,可以实现不规则的外观呈现。同时还介绍了TemplateField的用法和FormView与DetailsView的区别。 ... [详细]
  • 导出功能protectedvoidbtnExport(objectsender,EventArgse){用来打开下载窗口stringfileName中 ... [详细]
author-avatar
小小小小修领_233
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有