Using LINQPad with MongoDb and NoRM by ThinqLinq

Using LINQPad with MongoDb and NoRM

I’ve recently been working on a project that might be a good fit for the rising wave of Document Databases espoused by the rising NoSQL movement. Unlike the traditional Relational Databases like SQL Server, Document Databases can store object hierarchies, or unshaped data for quick and efficient saving and retrieval. There are quite a number of these databases appearing, including MongoDb, CouchDb, RavenDb. Wikipedia also has a listing of Document Databases with links to other options.

Typically, these data stores expose their data through XML or JSON interfaces. Luckily,  many of these databases also have LINQ providers to make interfacing with the systems easier. For example, if you are using MongoDb, you can use a provider like the NoRM (No-ORM) provider. Today I had the pleasure of sitting in on a webcast that Michael Kennedy of DevelopMentor did showing MongoDb with NoRM. During the presentation the question came up regarding using LINQPad in the environment. I promised to tell them how to do this, so here you go:

Install and Startup Mongo

The first step you need to do is download and startup MongoDb. To download it, go to the MongoDb site and download the version appropriate to your OS. Once you’ve downloaded it, unzip the files to your favorite directory. From the command line, start Mongo by entering the following from the bin directory that you unzipped:

mongob -dbpath=c:\projects\data\mongo

Of course, this assumes you want to put the database in the c:\projects\data\mongo path. The path does need to be present before running this command. You will be prompted to open a firewall hole for Mongo. Once you’re done, Mongo should be up and running.

Preparing NoRM

Now that the database is running, we need to prepare the .Net provider. Download the NoRM provider through Github, or directly from their download site. Unzip these files and open the appropriate sln file in Visual Studio. NoRM works in VS 2008 and NoRM – VS2010 works in VS 2010. Once you open it, compile it. Now you’re ready to roll. If you’re not sure how to get started with the NoRM provider, take a look at the many unit tests that they’ve provided to get up and running quickly.

Using LINQPad

Assuming you’ve downloaded and installed LINQPad, you should now be ready to start consuming Mongo through NoRM in LINQPad. Start by opening LINQPad and creating a new query. In order to work with our database, we need to create some class structures. As a result, you need to select the C# Program or VB Program option under the Language drop-down. (I’m choosing to do this in C# this time because the NoRM provider doesn’t fully support VB expression trees at this point.)

image 

By selecting the Program option, we can now create not only LINQ queries, but entire classes and methods. Scroll to the bottom of the code window and add a class describing the shape that we want to save and retrieve.


class Post
{
	public ObjectId Id { get; set; }
	public string Title { get; set; }
	public string Content { get; set; }
	public DateTime PubDate { get; set; }
	public string[] Categories { get; set; }
}

Keeping with the typical samples I have on this site, I’m modeling a Blog post. This will create a hierarchical shape containing posts with a collection of categories. Now that the shape is defined, we need to figure out how to insert and retrieve it using LINQPad.

To start, press F4 (or select Query and Query Properties from the menu). This will bring up a dialog to add references. In this dialog, click the Add button and locate the Norm.dll that you generated when you compiled it above when Preparing NoRM.

image

Before you close this window, select the “Additional Namespace Imports” tab at the top. This will allow us to add the Norm imports/using clauses. Add an import for Norm and Norm.Linq. (Notice here, you don’t include the “using” or “imports” keywords, just the namespaces that you want to import.) Once you’ve added the reference, close the dialog so that we can continue consuming Mongo.

image

In the code window, enter the following inside the body of the void Main() method that was generated when we selected the Program option in LINQPad:


using (var cn = MongoQueryProvider.Create("mongodb://127.0.0.1/ThinqLinq?strict=false"))
{
	var posts = cn.DB.GetCollection<Post>();
	posts.Insert(new Post
	{
		Title="Testing Linqpad",
		Content="This is a test using LinqPad",
		PubDate=DateTime.Now,
		Categories = new string[] {"NoSql", "MongoDb", "LinqPad"}
	});

	var foundPosts = from p in new MongoQuery<Post>(cn)
			where p.Title == "Testing Linqpad"
			select p;
		
	foundPosts.Dump();
}

Let’s step through this code a bit. The first line sets up our connection to the Mongo Database. We pass in the URI of the server (mongodb://127.0.0.1/) along with the name of the “database” that we want to use, or create if it hasn’t already been created (“ThinqLinq”).

This connection behaves similarly to the LINQ to SQL DataContext or Entity Framework’s ObjectContext. As with those contexts, we next need to access the “Table” for the type that we are trying to create. We do that by accessing the GetCollection method of the DB object referencing the type that we want to get (Post).

With the reference to the posts collection, we can insert a new Post object into our database by calling the Insert method. Notice, unlike a traditional RMDBS, we have not actually created anything in the database yet. This is the great thing about a Document Database. We can save our objects directly in the database without having to create the structures ahead of time.

With the object inserted into the database, we can now fetch it back using a standard LINQ query. The only difference we see here to the pattern in other LINQ providers is that we access the data source by calling MongoQuery passing in the Type that we want to fetch and the connection object that we declared at the top of the method. We view the results by calling the LINQPad Dump extension method on the results. Once completed, here’s a screen shot including the final code and results. Notice that the results do include the three items we added in the Categories array along with the single post record.

image

Interestingly, the built-in performance timer and Lambda expression options in LINQPad still work here even though we aren’t accessing a traditional database. The SQL tab remains blank because we aren’t issuing a SQL statement to Mongo.

Document Databases and the whole NoSQL movement are quite intriguing. There are plenty of times where relational data stores are a better fit, particularly when you are needing to report on related objects rather than working with object hierarchies natively. However, tools like MongoDB and NoRM make working with non-traditional hierarchical document stores quite easy as well and point to some interesting options for data storage and retrieval for other needs.

Posted on - Comment
Categories: C# - LinqPad -
comments powered by Disqus