Click here to monitor SSC
  • Av rating:
  • Total votes: 31
  • Total comments: 6
Jeremy Jarrell

MongoDB Basics for .NET by Example

26 March 2012

MongoDB is one of the more intriguing 'NoSQL' databases to emerge from 'Cloud' computing. Sometimes, the best way of understanding a rather different technology is to get stuck-in and try it out, so Jeremy Jarrell shows how to get started with a simple ASP.NET MVC project that uses MongoDB.

NoWhat?

Odds are that you’ve heard rumblings of a new set of technologies lumped under the umbrella of NoSQL. Discussions of this ‘NoSQL thing’ are often accompanied by exotic names like Cassandra, Project Voldemort, or CouchDB. You may have even heard of one of the most popular of these technologies, MongoDB.

MongoDB (derived from ‘humongous’) is a NoSQL database offering from 10Gen. Although MongoDB is developed and maintained by 10Gen, it is an open source product whose source code is freely available on GitHub and available for commercial use entirely for free. Paid support is available from 10Gen.

MongoDB was developed as a database that would scale gracefully across several machines over a network, often referred to as horizontal scalability. It was also designed as a data-store for web applications. MongoDB is a proud member of the NoSQL family, of the ‘document-database’ type. This means that objects are stored as markup in documents. Since document databases store information as schema-less data organized into collections, they can be thought of as a middle ground between the rich object models available in a relational database and the extreme lightweight data storage of a simple key/value store. The schema is imposed by the application rather than being inherent in the way the data is stored. However, ad-hoc querying is made possible due to the use of secondary indexes

Also differing from many of its NoSQL counterparts, MongoDB provides some level of transactional guarantee through strong consistency, rather than the full write-ahead logging of an RDBMS. While not fully ACID compliant MongoDB can, by using safe mode rather than ‘fire and forget’ IP messages, guarantee that operations are replicated across other peers in the MongoDB cluster within the scope of a transaction. This feature combined with Journaling allows MongoDB to provide some level of durability in the event that a single MongoDB node goes down. As this type of transactional replication does carry a performance penalty, the amount of replication necessary per transaction can easily be scaled up or down—or disabled completely—to meet your needs.

Getting MongoDB Up and Running

MongoDB can be up and running in a few easy steps…

  1. Download the latest stable production release for Windows from here. While MongoDB is available for both 32-bit and 64-bit flavors of Windows, only the 64-bit flavor is intended for production. MongoDB stores its datasets in memory so the addressing limitations in the 32-bit build will cause your database to fail if your data ever exceeds 2GB.
  2. Create a directory on your hard drive at c:\data\db. This is the default location where MongoDB will expect to store its data files.
  3. In the unpacked MongoDB zip file you’ll find a /bin/ directory containing several executables. Running mongod.exe from the command line will result in a command window displaying several messages pertaining to initialization and listening. Congratulations! You’ve just launched your first instance of MongoDB.

    Launching the initial instance of MongoDB

  4. Now, return to the /bin/ directory and run mongo.exe from the command line, which is the MongoDB administration shell. By default, the shell will connect to the MongoDB instance that you just started.

    Connecting the shell to the initial instance

  5. From the mongo.exe client, enter the following command…

       > db.my_docs.save({a:'me'});

Congratulations! You’ve just created your first MongoDB collection (my_docs) and inserted your first document ({a:‘me’}) into it!

Running MongoDB as a Windows Service

While launching MongoDB from the command line was easy, we obviously won’t be launching the executable by hand in a production environment. In the Windows world, we’ll launch the application as a Windows Service in order to ensure that it’s available each time the machine starts. Luckily, mongod.exe ships with the capability to install itself as a Windows Service.

You can install mongod.exe as a Windows Service by following these simple steps…

  1. Using a command prompt launched as an Administrator, navigate to the directory where you unzipped the MongoDB download.
  2. Using a text editor, create a text file beside the bin/mongod.exe executable called mongod.conf and enter the following information in it:

    dbpath = c:/data/db
    logpath = c:/mongo/logs/mongo.log log
    append = true

The dbpath parameter specifies where the mongo database files will live while the logpath parameter specifies the location of the log files. Make sure that both the ‘data/db’ and ‘mongo/logs’ directory already exist on disk. The logappend parameter prevents the log file from being truncated each time the service is restarted.

The dbpath file

  1. From the command prompt, enter the following command to install mongodb as a service.

        > mongod --config "c:\mongo\bin\mongod.conf" install
  2. From the command prompt, enter the following command to start the MongoDB service.

        > net start "Mongo DB"

To verify that the service is running correctly, simply fire up your mongo.exe client and begin interacting with MongoDB as before. By default, the mongo.exe client will connect to an instance of mongod.exe listening on 127.0.0.1, which is the instance now running as a Windows Service.

Working with MongoDB from Your .NET Application

Now that you have the MongoDB service up and running, it’s time to start working with it from your .NET application. Luckily there are several mature .NET drivers for MongoDB available. We’ll be using the official .NET driver from MongoDB created by 10Gen which is available from here.

Downloading the Drivers

10Gen makes the .NET drivers available from their GitHub repository in both MSI and ZIP format. For our purposes, you can simply download the ZIP of the drivers, unzip them to your machine, and reference the DLLs directly from your project.

Alternatively, the drivers are also available from the NuGet official package source as a NuGet package which can be added directly to your solution.

Connecting to the MongoDB database

To get started working with MongoDB you’ll need establish a connection to both your MongoDB server and database.

const string ConnectionString = "mongodb://localhost/?safe=true";
var server = MongoServer.Create(ConnectionString);
var blog = server.GetDatabase("blog");

The connection string above simply connects to the default instance of MongoDB running on the local machine. While this is a pretty simple connection string, it’s possible to specify more advanced options such as a username and password or other options to use while making the connection. For example, the safe=true option will notify you of any errors that occur during saves or inserts. You can see the full capabilities of the connection string here. If you find yourself taking advantage of these more advanced features then you should use the MongoUrlBuilder class to construct a connection string that meets your needs.

The server.GetDatabase("blog") method returns the database on the current MongoDB instance with the name of “blog”. If no such database exists, then it will be created for you automatically when you insert your first document.

Working with Collections

A Collection in MongoDB is loosely akin to a Table in SQL databases. Just as a Table may contain many related Rows, a Collection may contain many related Documents.

var posts = blog.GetCollection<Post>("posts");

The blog.GetCollection<Post>("posts") method returns a collection named “posts” in the given database. Just as with the GetDatabase("blog") method, if no such collection exists it will be created for you automatically when your first document is inserted into it.

Note that the GetCollection<Post>("posts") method is strongly typed which makes working with Posts quite convenient since it is not necessary to cast them to the proper type. However, since Collections in MongoDB are Schema-less there are weaker overloads of GetCollection() available in the event that you would like to store items of differing structures in the same collection.

Now that we have a reference to our collection of posts, we can begin saving documents to the collection using the Save() method. This method is actually a special type of command known as an ‘upsert’, which combines an update with an insert. Upserts are smart enough to determine whether or not an item already exists in the collection, and if so, simply update the existing item with the new data. Otherwise, a new item will be inserted in to the collection. This is a simple concept that can save you from a lot of tedious code when deciding whether to use an insert or an update.

var firstPost = new Post("First post!",
"This is the first post on my very popular blog.");
posts.Save(firstPost);

After executing this code we can view the post by inspecting the contents of our MongoDB instance using the mongo.exe shell.

  1. From the command line, launch the mongo.exe executable.
  2. Enter the command show dbs to display the databases available on the instance, including our new “blog” database.
  3. Now that we’ve verified the “blog” database was created, we can switch to it using the use blog command.
  4. To determine if the “posts” collection has been created in this database, we can view all collections with the show collections command.
  5. Finally, we can view our actual document in “posts” using the db.posts.find().toArray() command to retrieve the first 10 items in the collection.

Viewing the details of the document

Note that the MongoDB driver has mapped our “Id” field to a field called “_id”. These are the keys that MongoDB uses internally to identify Documents as well as determine whether or not the Document is being inserted anew or simply updated. While this conversion is transparent when working with Ids in the application code, we’ll need to remember to reference “_id” when querying MongoDB for items by their Id.

You may have noticed that we’ve chosen to represent Id as an ObjectId. Since NoSQL databases are designed to scale horizontally across multiple nodes the inherent uniqueness of an ObjectId ensures that Id will always be given a unique value across all nodes.

Working Directly with BSON

Although we’re working with domain objects, such as Post, the .NET driver also allows us to work directly with the BSON objects that represent the items natively in the MongoDB database. BSON is a binary version of the popular JSON data format which combines both efficiency of storage with ease of serialization. Although you have full access to the BSON serialization library, MongoDB.Bson, which is used by the .NET MongoDB driver, in most cases you can leave the automatic serialization to the driver.

Querying

Now that we’ve stored our first MongoDB document, let’s talk about ways to retrieve from our collection.

The MongoDB driver provides a rich library for the creation of complex queries, however, we can easily locate our post by querying by the title.

var query = Query.EQ("Title","First post!");
foreach (var matchingPost in posts.Find(query))
{
}

In addition, we can return all posts in the collection by using the FindAll() method.

Adding to our Blog

Imagine that our readers are asking for the chance to join in the conversation. Let’s add a collection of Comments to our Post object.

var firstPost = new Post("First post!", "This is the first post on my very popular blog.");
firstPost.Comments.Add(new Comment("I completely agree!"));
firstPost.Comments.Add(new Comment("Me Too"));

Note that even though Comments are separate objects than Posts, in MongoDB they are serialized into the same document.

The comments displaying within the same document

Now imagine that our readers have mentioned they would like to add titles to their comments. We can simply add the Title field to our Comments object and begin working with it. Any Comments with Titles will be easily stored alongside Comments without Titles.

var secondPost = new Post("Second post!", "The great posts just keep coming!");
secondPost.Comments.Add(new Comment("Doubtful", "I'm not sure I agree with you..."));

Showing contents with titles

Remember that although we can store Comments with Titles alongside those without, it’s still the responsibility of your application to know how to handle both types of Comments when it encounters them.

Where MongoDB Fits for You

Hopefully this article has given you some insight into why NoSQL databases like MongoDB have surged in popularity in recent years. If you’d like to see a full working a solution of a MongoDB application with .NET in action you can download the source code for this article from the speech bubble at the top of this article. Remember that this sample solution has been designed to illustrate the steps required to interact with MonogDB in the clearest possible way and doesn’t necessarily reflect the coding style or best practices that you should use in a production application.

Since NoSQL databases can happily coexist alongside traditional relational databases, remember that NoSQL should be thought of not as ‘NO SQL’ but rather as ‘Not-only SQL’. Just as not every scenario is a best fit for a NoSQL database, not every scenario is a best fit for a relational database. But now you have the option to choose the best tool for the job.

Special thanks to Robert Stam, 10Gen Software Engineer and maintainer of the official MongoDB C#/.NET driver, for lending his technical expertise and insight to this article.

Jeremy Jarrell

Author profile:

Jeremy Jarrell is a software developer specializing in desktop application development with the .NET platform. He is heavily involved in the .NET developer community both as a regular contributor to open source and as a frequent presenter at user groups throughout both the Pittsburgh and Philadelphia areas. His interests include client application technologies, developer productivity, and leading edge developer techniques such as test-driven development. He can be reached through his website at www.JeremyJarrell.org.

Search for other articles by Jeremy Jarrell

Rate this article:   Avg rating: from a total of 31 votes.


Poor

OK

Good

Great

Must read
Have Your Say
Do you have an opinion on this article? Then add your comment below:
You must be logged in to post to this forum

Click here to log in.


Subject: Newb question
Posted by: Anonymous (not signed in)
Posted on: Wednesday, April 11, 2012 at 7:20 AM
Message: Hi Jeremy,

I assume there is just no way to retrieve a Comment collection containing comments across every posts right ?

Subject: RE: Newb question
Posted by: jeremyjarrell (view profile)
Posted on: Friday, April 13, 2012 at 5:25 AM
Message: Good question. I don't believe there's a way to simply retrieve all Comments without retrieving all Posts since Comments are a nested document within the Post document.

You could, however, retrieve all Posts and then project them into a collection of Comments on the server using LINQ.

Hope that helps,
Jeremy

Subject: Mongo as a Windows Service
Posted by: brainiacrk (view profile)
Posted on: Tuesday, May 01, 2012 at 9:09 PM
Message: Great article.

To install Mongo as a Windows Service, I had to first initiate the command:
mongo --logpath "C:\mong\bin\mongod.conf" --install

That worked for me for Windows 32-bit V2.0.4, as opposed to mongod --config "c:\mongo\bin\mongod.conf" –install, which did not work. Thanks!

Subject: Mongo as a Windows Service
Posted by: brainiacrk (view profile)
Posted on: Wednesday, May 02, 2012 at 6:35 AM
Message: Great article.

To install Mongo as a Windows Service, I had to first initiate the command:
mongo --logpath "C:\mong\bin\mongod.conf" --install

That worked for me for Windows 32-bit V2.0.4, as opposed to mongod --config "c:\mongo\bin\mongod.conf" –install, which did not work. Thanks!

Subject: RE: Mongo as a Windows Service
Posted by: jeremyjarrell (view profile)
Posted on: Sunday, May 06, 2012 at 7:08 AM
Message: Great tip, brainiacrk! Thanks for sharing!

Subject: newb question
Posted by: hawkman (view profile)
Posted on: Tuesday, June 18, 2013 at 3:18 AM
Message: Hi Jeremy

I just this up and trying to run it completely. However I am getting error while performing Membership.CreateUser(...):

Unable to connect to SQL Server database.

Not sure where to start for trouble shooting..
Database connection is there because the blogs are created each time I hit the home button..
What do you think?
Thanks.

 

Top Rated

Acceptance Testing with FitNesse: Multiplicities and Comparisons
 FitNesse is one of the most popular tools for unit testing since it is designed with a Wiki-style... Read more...

Acceptance Testing with FitNesse: Symbols, Variables and Code-behind Styles
 Although FitNesse can be used as a generic automated testing tool for both applications and databases,... Read more...

Acceptance Testing with FitNesse: Documentation and Infrastructure
 FitNesse is a popular general-purpose wiki-based framework for writing acceptance tests for software... Read more...

TortoiseSVN and Subversion Cookbook Part 11: Subversion and Oracle
 It is only recently that the tools have existed to make source-control easy for database developers.... Read more...

TortoiseSVN and Subversion Cookbook Part 10: Extending the reach of Subversion
 Subversion provides a good way of source-controlling a database, but many operations are best done from... Read more...

Most Viewed

A Complete URL Rewriting Solution for ASP.NET 2.0
 Ever wondered whether it's possible to create neater URLS, free of bulky Query String parameters?... Read more...

Visual Studio Setup - projects and custom actions
 This article describes the kinds of custom actions that can be used in your Visual Studio setup project. Read more...

.NET Application Architecture: the Data Access Layer
 Find out how to design a robust data access layer for your .NET applications. Read more...

Calling Cross Domain Web Services in AJAX
 The latest craze for mashups involves making cross-domain calls to Web Services from APIs made publicly... Read more...

Web Parts in ASP.NET 2.0
 Most Web Parts implementations allow users to create a single portal page where they can personalize... Read more...

Why Join

Over 400,000 Microsoft professionals subscribe to the Simple-Talk technical journal. Join today, it's fast, simple, free and secure.