How to "remember" / force yourself to include linked documents which can be included when doing queries / loads

59 views
Skip to first unread message

Karl Cassar

unread,
Sep 15, 2014, 8:31:46 AM9/15/14
to rav...@googlegroups.com
Sometimes, I'm checking my code or code of others and find that a sub-query on RavenDb was not 'Included' in the previous query.  This would result in two or more calls to the database.  The problem with this is that one would not notice this most of the time especially during testing or unit-tests.  

I know there exists the maximum queries in a session, but sometimes that is not reached so no errors would be thrown.  These would only be discovered if the application is performing poorly in production or stress tests.

Are there any guidelines, or tips how one can "remember" to include any documents which can be included?  

Regards,
Karl

Oren Eini (Ayende Rahien)

unread,
Sep 15, 2014, 8:35:17 AM9/15/14
to ravendb
public static T LoadIfIncluded<T>(this IDocumentSession self, string id)
{
       if(self.Advanced.IsLoaded(id) == false)
           throw new InvalidOperationException(id + " not already loaded");
     return self.Load<T>(id);
}



Oren Eini

CEO


Mobile: + 972-52-548-6969

Office:  + 972-4-622-7811

Fax:      + 972-153-4622-7811




--
You received this message because you are subscribed to the Google Groups "RavenDB - 2nd generation document database" group.
To unsubscribe from this group and stop receiving emails from it, send an email to ravendb+u...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Karl Cassar

unread,
Sep 15, 2014, 8:45:42 AM9/15/14
to rav...@googlegroups.com
Hi Oren,

I'm actually already using something similar to that.  However, the problem I found is that sometimes, if say a particular method which loads a product by Id is used in two different logic paths, in one path it should be already loaded, while in the other it is like the "initial query" and needs to actually loaded.

The other thought I had about this was that for the 2nd case, I would create another method which would actually load it, and then call the other method which expects it to be loaded already.  Any thoughts on this?

Regards,
Karl

Oren Eini (Ayende Rahien)

unread,
Sep 15, 2014, 8:48:56 AM9/15/14
to ravendb
I don't follow



Oren Eini

CEO


Mobile: + 972-52-548-6969

Office:  + 972-4-622-7811

Fax:      + 972-153-4622-7811




Kijana Woodard

unread,
Sep 15, 2014, 10:58:45 AM9/15/14
to rav...@googlegroups.com
What if you log / display the query count [mini profiler?] and then as a dev/qa step, be on the lookout for values greater than 1.

Karl Cassar

unread,
Sep 16, 2014, 3:26:20 AM9/16/14
to rav...@googlegroups.com
Hi Kijana,

Yes that's another thought that came in mind - Maybe decorate such methods with an Aspect (using Postsharp), say [ShouldOnlyExecuteOneRequest].  Then, the aspect would check the method variables for an IDocumentSession, see how many requests it had before the method started, and see how many it had after it started.  If there is more than 1, it would throw an error.  

Basically I wanted to know if there were any "proper" ways to do this, rather than rolling your own solution as I didn't want to reinvent the wheel.  However it seems that is the way forward.  

Another logic I do is I don't use the session.Load directly, but always pass it through another extension method (GetById(this session)) which always expects the item to be pre-loaded in session.  Then, I have to specifically pass as parameter that this is not expected to be in session.  This way, it lets one stop and think about including.  

However, a big issue i'm facing is that in TDD, session etc are mocked - Hence, this is something which only crops up at run-time when using the actual system, not during the unit-testing stage.

Regards,
Karl 

Kijana Woodard

unread,
Sep 16, 2014, 10:29:55 AM9/16/14
to rav...@googlegroups.com
In one system I wrote, I did assert that only one request occurred in the unit tests.

When interacting with raven, I don't mock out the session, I use it directly against an in memory database for the unit tests....for exactly this reason. I want to be as sure as possible about the runtime behavior from my tests. Frankly, I had to go back to sql server  for a project and lack of this feature was maddening. Spent tons of time mocking and still had no assurance that the system would _run_ as expected.

The trick is to put the db access in a meaningful unit instead of one of those "layered monstrosities".

--
You received this message because you are subscribed to the Google Groups "RavenDB - 2nd generation document database" group.

Karl Cassar

unread,
Sep 16, 2014, 10:57:34 AM9/16/14
to rav...@googlegroups.com

So if you for example wanted to test loading an item with id Product/1, you would actually save it in database and actually fetch it?  Not mock the session object?

It would help in ironing out these one-request issues, but I think it would add a lot of test code ?

Regards,
Karl

Kijana Woodard

unread,
Sep 16, 2014, 11:59:39 AM9/16/14
to rav...@googlegroups.com
Yes.

Not that much code.

Context:
session.Store(new Product { Id = "products/1" });

Because:
sut.Execute();

Assert:
Assert.True(whatever);

Fwiw, I usually only bother storing the parts of the product that are relevant to the test at hand.

--
Reply all
Reply to author
Forward
0 new messages