How to map Mongodb->runcommand results to a business class method summary in C #

Source: Internet
Author: User

Objective

has not actually used MongoDB, recently a project used, stepped on some pits. This article describes the problems that are encountered when mapping Mongodb->runcommand results to business classes, and explores the various approaches.

The data in the collection is this:

Use the Find command to query the data:

Db.runcommand ({"Find": "Test", Limit:2, Sort:{addtime:-1}})

The data structure that is returned by the query is this, and the required information is in Firstbatch:

{"cursor": {"Firstbatch": [   {  "_id": ObjectId ("5ad0042944fd3929db6b869f"),  "Name": "John Doe",  "Addtime" : Isodate ("2018-04-12t01:13:18.965z")  },   {  "_id": ObjectId ("5ad003e844fd3929db6b869e"),  "Name": " Zhang San ",  " Addtime ": Isodate (" 2018-04-02t01:11:18.965z ")  }]," id ": Numberlong (0)," ns ":" Test.test "}," OK ": 1.0}

The following will run the Find command in C # to execute the query and map the results to the custom Personinfo class.

Private class PersonInfo {public  string Id {get; set;}  public string Name {get; set;}  Public DateTime addtime {get; set;}}

It is important to note that the attribute ID in Personinfo and the name in document _ID are somewhat different and need to be mapped. Because different deserialization methods are used in different ways, the following are described below.

Using Json.NET

Because json.net use more, the basic idea is to use it to deserialize the Bson, but the JSON and Bson are different, can not be used JsonConvert.

However, Json.NET provides a new package Newtonsoft.Json.Bson to parse the Bson data and provides an example.

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

This example is a bit out of date, with the Bsonreader I have replaced with Bsondatareader.

byte[] data = convert.frombase64string ("mqaaaajoyw1laa8aaabnb3zpzsbqcmvtawvyzqaju3rhcnreyxrlamdgkwe8aqaaaa=="); MemoryStream ms = new MemoryStream (data), using (Bsondatareader reader = new Bsondatareader (ms)) {Jsonserializer Serialize R = new Jsonserializer ();  Event e = serializer. Deserialize<event> (reader);  Console.WriteLine (E.name); Movie Premiere}

It seems that there is a byte array on it, and then see bsondocument there is just one way to Tobson, get byte[].

Idea: First map the results of the RunCommand to Bsondocument, then find the Firstbatch, then tobson it, and then use Newtonsoft.Json.Bson deserialization.

Everything looks very easy!.

Code up right away:

  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);

An array cannot be the root element of a Bson, so this defines a personlist class:

Private class Personlist {public  string Name {get; set;}  [Jsonproperty (propertyname = "Value")]  Public personinfo[] List {get; set;}}

It is important to note that the  GetElement(“firstBatch”).ToBsonDocument() data format returned in the above code is as follows:

This uses Jsonproperty to map value to list.

There is also a difference in the name of the attribute in the person class and in document, and it needs to be mapped:

Private class PersonInfo {  [Jsonproperty (propertyname = "_id")]  [Jsonconverter (typeof (Objectidconverter))] Public  string Id {get; set;}  public string Name {get; set;}  Public DateTime addtime {get; set;}}

One is also used here JsonConverter(typeof(ObjectIdConverter)) , because Objectid cannot be converted directly to string, so a Objectidconverter class is defined:

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 ();  } }

There is also an important way to deserialize:

  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;   }  }

Now run the program and look at it:

But it feels so complicated, it's a bend and a bend.

Using MongoDB. NET driver Built-in

Words so commonly used functions, the SDK should be built-in only, why Shejinqiuyuan,.

Since RunCommand can pass a type, the SDK should support deserialization of the custom type.

Try to define a new class based on the returned results:

  [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 these are the SDK built-in attribute, the role of everyone should be able to at a glance.

Then look at the code that queries this block:

   var FindCommand = Bsondocument.parse ("{\" find\ ": \" Test\ ", Limit:1, Sort:{addtime:-1}}");   var findresult = database. Runcommand<findcommandresult> (FindCommand);

The code runs up:

This method is more straightforward and simpler than json.net.

How to use Find assignments

In order to deserialize, to adapt to MONGODB, defined some non-business meaning of the type, add a lot of attribute annotations, feeling is not direct dominance.

You may need only a few fields in the data, or there is no need to define the type at all, just put it in a list.

We also looked at the definition of bsondocument and found that it was possible to deserialize the command as Bsondocument, and then use GetElement to get the value of the related field based on the returned data structure.

The code is as follows:

   var FindCommand = Bsondocument.parse ("{\" find\ ": \" Test\ ", Limit:2, Sort:{addtime:-1}}");   var fdasheng178.comindresult = database. Runcommand<bsondocument> (FindCommand)    . GetElement ("cursor"). Value.tobsondocument ()    . Getelelongboshyl.cnment ("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 (),     };    }). Hbs90.cnTjyz521.comoList ();

Return directly after running List<PersonInfo> , more close to business requirements.

This is the simplest way in this article.

If you do a more general point, you can automatically instantiate the correlation type here by reflection, but this is not as straightforward as using the SDK built-in deserialization.

How to map Mongodb->runcommand results to a business class method summary in C #

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.