How to MongoDB in C# — Part 2

Stas Rivkin
7 min readJan 24, 2017

--

“How to MongoDB in C#” will be a multi-part blog-posts series:

  1. How to MongoDB in C# — Part 1
  2. How to MongoDB in C# — Part 2
  3. How to MongoDB in C# — Part 3
  4. How to MongoDB in C# — Part 4

Recap on MongoDB for .NET

In the previous post, we mainly talked about MongoDB’s object-mapping inside C#. We will continue our introduction, but this time with MongoDB’s core ingredients.

When you add MongoDB to your project using NuGet, Three new references will be added to your project:

Let’s explore them:

  • MongoDB.Bson contains the code for the Bson object model — BsonDocument, BsonValue etc. as well as Mapping from POCO to Bson and vice-verse.
  • MongoDB.Driver.Core contains all the server related connectivity — how to talk to the server, how to make sure to which server a specific commands and queries will be sent to, connection-pool etc.
  • MongoDB.Driver a lightweight syntax wrapper on top of MongoDB.Driver.Core

Note that usually you’ll never call the Core library directly, only through interacting with the Bson & Driver

MongoDB’s client objects

In order for your application to communicate with MongoDB, we need to get familiarize with the following objects:

MongoClient

Point of entry, thread-safe object. May be saved in a static variable or even inside an IOC container.

Also, this class can be safely created and re-created multiple times as long as you use the same connection settings (MongoDB will use the same connection-pool under the hood).
There are several ways for you to pick on how to initialize a MongoDB client:

Note: By default, MongoDB connects to port 27017 on your localhost.

**MongoClientSettings, contains:

  1. Servers
  2. Timeouts
  3. Credentials
  4. Pool sizes
  5. Read preferences (when a read is required from other then the primary server)
  6. SSL settings
  7. Write concern — what durability you would like your write to persist to
  8. ClusterConfigurator
Note: There are many properties you can set here, but MOST of them are fine as they are.

ClusterConfigurator is an important option, as it allows you to change different configuration (hence the name). It requests an Action delegate which accepts ClusterBuilder

Than, why is it important? It allows you to listen to what happens “under the hood” in MongoDB (the core events):

Take “Subscribe” method for example, it accepts any type as long as it implements IEventSubscriber, therefore enables you to hook to MongoDB events.

Note: "TraceCommandsWith" is an extension method, which registers TraceSourceCommandEventSubscriber to listen for all command-event types

Let’s see how we can track the “find a single developer” request-response. Fortunately MongoDB provides pre-defined set of subscribers:

We are going to use SingleEventSubscriber to track a single request and a single response.

Or we can use ReflectionEventSubscriber by specifying which events we are interested in internally

You can check which events are available in the MongoDB.Driver.Core.Events namespace and for a full list of MongoDB Commands.

By the way, as a developer you won’t have to deal with connection management related stuff. MongoDB handles all of the connection managements for you (Closing, disposing and release of connections back to the pool for later re-use)

IMongoDatabase

A new instance implementing IMongoDatabase can be acquired by calling MongoClient‘s “GetDatabase” method:

Well.. the actual method interface is:

As you can see, there is an optional parameter of MongoDatabaseSettings, interesting enough MongoDB lets you to override some of the settings you defined on the MongoClient and also pass MongoCollectionSettings to further override Client and/or Database settings when creating your IMongoCollection (we will address it later on)

IMongoDatabase, is responsible for all collection related CRUD operations and some more, such as (Most of those CRUD operations have an async support as well):

  • Create a collection
  • Drop a collection
  • Rename a collection name
  • Get specific collection
  • Lists your collection — provides a metadata information for each of your collections in a specific IMongoDatabase instance, you can use it to log it during debug time or whatever comes to mind.

we can see here “options”, “indexes” among other trivial things

  • options refer to MongoXXXSetttings passed at creation
  • idIndex refer to different indexes applied on this collections (we can see the default index — key “_id” of which we discussed in the previous post)
  • “ns : csharp.developers” — the “csharp” is not related to the language I’m writing in, it just how I named the database where the “developers” collection resides in.

IMongoCollection<TDocument>

The IMongoCollection is your gateway to all of MongoDB’s goodies, using it you will gain access to:

  1. Indexes API
  2. Aggregation API
  3. CRUD API

IMongoCollection also supports AsQueryable:

By extending C# IQueryable<T>, IMongoQueryable<TDocuement> adds MongoDB specific methods and giving it an async support for the LINQ API.

Note: Deleting your collection during runtime and re-accessing it, won't throw any exception. Next time you try to approach your collection with a query of some sort, MongoDB will automatically re-create the collection and run your query against it.

So.. Why use TDocument?

as I mentioned in the previous post everything is a Document or to be more precise everything is a BsonDocument when using the C# API. However, you don’t actually have to create a strongly typed class to populate it with values returning from MongoDB. For example, consider the Developer class we introduced in the previous post.

In the example below, we will look at the same data once populated in a Developer instance and in the second time inside MongoDB’s base class, BsonDocument.

Don’t wrap your head around the query syntax, we will get to it.. eventually. We are looking for all developers and telling MongoDB there can be only one (which is basically what we expect since we inserted only “John smith”)

Developer:

Now, let’s zoom-in into Developer represented as a BsonDocument. The BsonDocument, is in fact a key-value storage which holds a lot of properties.

Personally, I find it hard to believe you will ever use all of it’s properties in your code.

I have grouped most of the meaningful properties using OzCode‘s Reveal feature. Which enables me to focus on the properties and values I care about during debugging:

You can see, it can be very cumbersome to scan the BsonDocument for values (it depends on the depth of your JSON object).

Instead, I waved OzCode‘s magic wand and created a new Custom expressions to help me better understand my data:

The way it works, you can add any method/indexer call on the instance as long as the class has to offer that same method/indexer. Once I’ve created a new custom expression, OzCode will remember it even after the end of this specific debug session, so the next time you hover over an instance of type X, the new “Properties” you have just added will be there.

BsonDocument (re-examined):

This time I have gathered all of the data (again) I’m interested in the BsonDocument and created new “properties” at Debug-Time. Making it more easy for me to read the data.

I can even create my very own “custom expressions”:

What’s next

Up until now we’ve covered the top-most basics of:

  1. Relationship between JSON object and it’s twin C# brother, the Document, Object-Mapping, ID property (previous post)
  2. MongoClient
  3. MongoDatabase
  4. MongoCollection

Finally, we are getting to the real juicy stuff:

  • Analyzing CRUD operations results using OzCode’s Search, Collection Filter and Export features
  • Aggregation FW from C# perspective — simple and complex as one

Stay tuned!

The blog posts:

  1. How to MongoDB in C# — Part 1
  2. How to MongoDB in C# — Part 2
  3. How to MongoDB in C# — Part 3
  4. How to MongoDB in C# — Part 4

Originally published at blog.oz-code.com on January 24, 2017.

--

--

Stas Rivkin

Senior Developer & Consultant, instructor, international public speaker. Has a thingy for C# & also enjoying Angular/Node dev.