Over a million developers have joined DZone.

RavenDB: What are Tertiary Includes

· Database Zone

Build fast, scale big with MongoDB Atlas, a hosted service for the leading NoSQL database. Try it now! Brought to you in partnership with MongoDB.

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.


Now it's easier than ever to get started with MongoDB, the database that allows startups and enterprises alike to rapidly build planet-scale apps. Introducing MongoDB Atlas, the official hosted service for the database on AWS. Try it now! Brought to you in partnership with MongoDB.


Published at DZone with permission of Ayende Rahien, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

The best of DZone straight to your inbox.

Please provide a valid email address.

Thanks for subscribing!

Awesome! Check your inbox to verify your email so you can start receiving the latest in tech news and resources.

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

{{ parent.tldr }}

{{ parent.urlSource.name }}