Over a million developers have joined DZone.

RavenDB: What are Tertiary Includes

DZone's Guide to

RavenDB: What are Tertiary Includes

· Database Zone ·
Free Resource

RavenDB vs MongoDB: Which is Better? This White Paper compares the two leading NoSQL Document Databases on 9 features to find out which is the best solution for your next project.  

For a while, I was absolutely against this, in fact, I refused to implement this several times when asked, because it is complicate to do and indicate design problems in your domain model.

During a course today, I found out that I might want to refuse, but the feature is actually in the product for the last two+ years, we just didn’t know about this.

But what are tertiary includes in the first place?

Let us imagine that we have something like this:


Now, I want to load an order, but also show its Customer and Products. Those are secondary includes, and are very easy to do with RavenDB:

var orders = session.Query<Order>()

There is also a strongly typed option for this, of course.

What this does is instruct RavenDB to load into the session the Customer and the associated Products into the session, so when you do something like this:

var cust = session.Load<Customer>(order.Customer);

The value will be loaded from the session cache, without going to the sever. As I said, this is a feature that we have had for quite a while, and it is a really nice one, because it drastically reduce the number of queries that you have to make.

The problem is that some people want to take it one step further, they want to be able to search on an Order, but also load the Location of a Product. I don’t really like this, and as I said, when asked for this feature, I consistently said that it isn’t there because it represent a remnant of relational thinking in your design.

But as it turned out, we do support this, although quite by accident.

The reason is quite simple, we evaluate Includes only after we evaluate the TranformResults function. Which means that the TranformResults function gets to choose whatever you want to include. Here is how it works:

    TranformResults  = (database, results) =>
       from result in results
       select new 
         Order = result,
         Locations = result.SelectMany(x=>x.Lines).Select(x=>database.Load<Product>(x.Product).Location)

And then, you can just ask to Include(“Locations”), and you are pretty much set.

Except, that this is a really awkward thing to do, and I don’t really like it at all.

Sure, I don’t like this feature, but people will use it, and if it already there, we might as well make it elegant. Therefor, we now have the option of doing:

    TranformResults  = (database, results) =>
       from result in results
       let _ = database.Include(result.SelectMany(x=>x.Lines).Select(x=>x.Product))
       select result;

I think you’ll agree that this is much nicer all around, this tells the server to include the data, without us needing to explicitly ask this from the client.


Get comfortable using NoSQL in a free, self-directed learning course provided by RavenDB. Learn to create fully-functional real-world programs on NoSQL Databases. Register today.


Published at DZone with permission of

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}