Recently, I began to actively study and use the NoSQL solution of
RavenDB . So I decided to write an introductory post about how to start using RavenDB. In fact, this article is not much different from the “Hello world” instructions on
the project site (and I also took examples from there), but I will try to give some additions to what is written there. Just want to say that I am not an expert in RavenDB, and have been using it for my projects and tasks quite recently.
PS Why not MongoDB or CouchDB? I don't know, I just wanted to try this particular solution. Yes, and on Habré, this decision was not yet covered.
First you need to
download the latest version from the project site.
')
There is a Server folder in the archive, and there is a RavenDB server in it. If you run it, the Data folder with the base will appear next to it. Its size will be about 90MB, and this is due to the fact that the server reserves a large chunk of disk space for future data. If you want to reduce this size, you can add the parameter Raven / Esent / LogFileSize to the server configuration file, its default value is 16MB, as the
documentation says, but in fact the base size has decreased to 40MB after I set its value in 1.
A running server provides a web interface for accessing the database. By default, its address is https: // localhost: 8080. It allows you to manage documents that are in the database, add and delete indexes.

After the server is started and the database is created, open Visual Studio and create a console application. If you have NuGet installed, then right-click on References and click Add Library Package Reference. Go to the Online tab, find RavenDB there and install it. If you do not have NuGet, then
put it You need to add 3 assemblies from the Client folder (if you use .NET 3.5, then from the Client-3.5 folder):
- Newtonsoft.Json.dll
- Raven.Abstractions.dll
- Raven.Client.Lightweight.dll
Now you can start writing code. The following 2 lines create the DocumentStore class object, which will be used further to work with the database:
var store = new DocumentStore {Url = "http://localhost:8080" };
store.Initialize();
Now we will write several classes that will describe our domain model.
public class Product
{
public string Id { get ; set ; }
public string Name { get ; set ; }
public decimal Cost { get ; set ; }
}
public class Order
{
public string Id { get ; set ; }
public string Customer { get ; set ; }
public IList OrderLines { get ; set ; }
public Order()
{
OrderLines = new List ();
}
}
public class OrderLine
{
public string ProductId { get ; set ; }
public int Quantity { get ; set ; }
}
Please note that each class has a property Id, this is a mandatory condition, in this property RavenDB will store the unique number of your document.
The following code adds 2 documents to the database:
using ( var session = store.OpenSession())
{
var product = new Product
{
Cost = 3.99m,
Name = "Milk" ,
};
session.Store(product);
session.SaveChanges();
session.Store( new Order
{
Customer = "customers/ayende" ,
OrderLines =
{
new OrderLine
{
ProductId = product.Id,
Quantity = 3
},
}
});
session.SaveChanges();
}
The API implements the Unit of work pattern. First, we create a session object, then save the object in it (the Store method). At this stage, the product object is in the memory of our application and only after the call to the SaveChanges method is sent to the database.
After the application is executed, you can go to our server (http: // localhost: 8080) and on the tab with documents you can see 2 documents. If you open a document, you can see all its properties from the classes described above, as well as properties from the Document Metadata tab. They describe the .NET object type, the version of the RavenDB server, the name of the entities in the database.

To read these objects from your application, it’s enough to write the following code:
using ( var session = store.OpenSession())
{
var order = session.Load( "orders/1" );
Console .WriteLine( "Customer: {0}" , order.Customer);
foreach ( var orderLine in order.OrderLines)
{
Console .WriteLine( "Product: {0} x {1}" , orderLine.ProductId, orderLine.Quantity);
}
}
Those. we load a document with Id equal to 1 of the Orders entities.
For real-life applications, such a document search functionality is clearly not enough, so search by fields is necessary, and for this you need to add indices:
store.DatabaseCommands.PutIndex( "OrdersContainingProduct" , new IndexDefinition
{
Map = orders => from order in orders
from line in order.OrderLines
select new { line.ProductId }
});
Now you can select documents by ProductId:
using ( var session = store.OpenSession())
{
var orders = session.LueneQuery( "OrdersContainingProduct" )
.Where( "ProductId:products/1" )
.ToArray();
foreach ( var order in orders)
{
Console .WriteLine( "Id: {0}" , order.Id);
Console .WriteLine( "Customer: {0}" , order.Customer);
foreach ( var orderLine in order.OrderLines)
{
Console .WriteLine( "Product: {0} x {1}" , orderLine.ProductId, orderLine.Quantity);
}
}
}
This is quite enough to play with RavenDB. The only thing I would like to note is a couple of points:
- If you need to load a lot of objects, they must be divided into several parts and loaded in parts. This is because before the execution of the SaveChanges methods, all data is stored in memory, and it may simply not be enough. And to make more than 30 calls SaveChanges of the RavenDB library do not allow.
- When you search the database, the RavenDB engine returns data in pages of 128 pieces, so in order to display them all, you have to write something like this:
var query = session.Advanced.LuceneQuery<Order>( "OrdersContainingProduct" )
.Where( "ProductId:products/1" );
int actual = 0;
const int pageSize = 128;
int count = query.QueryResult.TotalResults;
do
{
var orders = session.Advanced
.LuceneQuery<Order>( "OrdersContainingProduct" )
.Where( "ProductId:products/1" )
.Skip(actual)
.Take(pageSize);
actual = actual + pageSize;
foreach ( var order in orders)
{
App.Logger.Info( "Id: {0}" , order.Id);
App.Logger.Info( "Customer: {0}" , order.Customer);
}
if (actual >= count)
break ;
} while ( true );
Links
Project siteWhy Raven DB?RavenDB - An Introduction