国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > C# > 正文

C#中如何將MongoDB->RunCommand結果映射到業務類的方法總結

2019-10-29 21:06:04
字體:
來源:轉載
供稿:網友

前言

一直沒實際用過MongoDB,最近有個項目中用了用,踩了一些坑。這篇文章會介紹將MongoDB->RunCommand結果映射到業務類時碰到的問題,以及對各種方法的探索。

Collection中的數據是這樣的:

mongodb,runcommand,結果集映射,command

使用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<Event>(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<BsonDocument>(findCommand)  .GetElement("cursor").Value.ToBsonDocument()  .GetElement("firstBatch").ToBsonDocument()  .ToBson();  var personList = DeserializeBson<PersonList>(findResult);

數組不能是Bson的根元素,所以這里定義了一個PersonList類:

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

需要注意的是上邊代碼中 GetElement(“firstBatch”).ToBsonDocument() 返回的數據格式是這樣的:

mongodb,runcommand,結果集映射,command

這里用了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<T>(byte[] data)  {   MemoryStream ms = new MemoryStream(data);   using (BsonDataReader reader = new BsonDataReader(ms, false, DateTimeKind.Local))   {    JsonSerializer serializer = new JsonSerializer();     T e = serializer.Deserialize<T>(reader);    return e;   }  }

現在運行程序看看吧:

mongodb,runcommand,結果集映射,command

但是感覺好復雜,過了一彎又一彎。

使用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<FindCommandResult>(findCommand);

代碼跑起來:

mongodb,runcommand,結果集映射,command

這個方式相比Json.NET更直接,更簡單。

使用查找賦值的方式

為了反序列化,適應MongoDB,定義了一些沒有業務意義的類型,加了很多的屬性注解,感覺還不夠直接顯性。

也許只需要數據中的某幾個字段,或者根本就沒必要定義類型,只需要放到一個列表中。

又查看了BsonDocument的定義,發現可以在運行命令時先反序列化為BsonDocument,然后再根據返回的數據結構使用GetElement獲取相關字段的值。

代碼如下:

   var findCommand = BsonDocument.Parse("{/"find/":/"test/", limit:2, sort:{AddTime:-1}}");   var findResult = database.RunCommand<BsonDocument>(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<PersonInfo> ,更貼近業務需求。

這是本文中最簡單的方式了。

如果做的更通用點,可以在這里通過反射自動實例化相關類型,不過這不如直接使用SDK內置的反序列化方式了。

總結

以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,如果有疑問大家可以留言交流,謝謝大家對VEVB武林網的支持。


注:相關教程知識閱讀請移步到c#教程頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 炉霍县| 淮阳县| 五指山市| 浙江省| 昌乐县| 繁峙县| 拜城县| 万山特区| 介休市| 淮北市| 宜宾县| 尚义县| 锡林郭勒盟| 南康市| 长宁区| 秦皇岛市| 太原市| 太白县| 苍溪县| 济阳县| 富阳市| 越西县| 延津县| 潞城市| 洞口县| 巢湖市| 清新县| 石泉县| 崇礼县| 清流县| 宿迁市| 三河市| 息烽县| 资中县| 平泉县| 邛崃市| 龙胜| 海林市| 来宾市| 琼结县| 额敏县|