Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>Use denormalized references:</p> <p><a href="http://ravendb.net/faq/denormalized-references" rel="noreferrer">http://ravendb.net/faq/denormalized-references</a></p> <p>in essence you have a DenormalizedReference class:</p> <pre><code>public class DenormalizedReference&lt;T&gt; where T : INamedDocument { public string Id { get; set; } public string Name { get; set; } public static implicit operator DenormalizedReference&lt;T&gt; (T doc) { return new DenormalizedReference&lt;T&gt; { Id = doc.Id, Name = doc.Name } } } </code></pre> <p>your documents look like - i've implemented the INamedDocument interface - this can be whatever you need it to be though:</p> <pre><code>public class Company : INamedDocument { public string Name{get;set;} public int Id { get; set; } public IList&lt;DenormalizedReference&lt;Contact&gt;&gt; Contacts { get; set; } public IList&lt;DenormalizedReference&lt;Task&gt;&gt; Tasks { get; set; } } public class Contact : INamedDocument { public string Name{get;set;} public int Id { get; set; } public DenormalizedReference&lt;Company&gt; Company { get; set; } public IList&lt;DenormalizedReference&lt;Task&gt;&gt; Tasks { get; set; } } public class Task : INamedDocument { public string Name{get;set;} public int Id { get; set; } public DenormalizedReference&lt;Company&gt; Company { get; set; } public DenormalizedReference&lt;Contact&gt; Contact { get; set; } } </code></pre> <p>Now saving a Task works exactly as it did before:</p> <pre><code>var task = new Task{ Company = myCompany, Contact = myContact }; </code></pre> <p>However pulling all this back will mean you're only going to get the denormalized reference for the child objects. To hydrate these I use an index:</p> <pre><code>public class Tasks_Hydrated : AbstractIndexCreationTask&lt;Task&gt; { public Tasks_Hydrated() { Map = docs =&gt; from doc in docs select new { doc.Name }; TransformResults = (db, docs) =&gt; from doc in docs let Company = db.Load&lt;Company&gt;(doc.Company.Id) let Contact = db.Load&lt;Contact&gt;(doc.Contact.Id) select new { Contact, Company, doc.Id, doc.Name }; } } </code></pre> <p>And using your index to retrieve the hydrated tasks is:</p> <pre><code>var tasks = from c in _session.Query&lt;Projections.Task, Tasks_Hydrated&gt;() where c.Name == "taskmaster" select c; </code></pre> <p>Which i think is quite clean :)</p> <p>As a design conversation - the general rule is that if you <em>ever</em> need to load the child documents <em>alone</em> as in - not part of the parent document. Whether that be for editing or viewing - you should model it with it's own Id as it's own document. Using the method above makes this quite simple.</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload