Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <h3>Thoughts on DDD decisions...</h3> <p>It sounds like you want to be able to do this:</p> <pre><code>var people = session.Query&lt;Person&gt;() .FetchMany(x =&gt; x.CreatedOrders) .Where(x =&gt; x.Id == personId); </code></pre> <p>You should just flip the query around, like so...</p> <pre><code>var orders = session.Query&lt;OrderHeader&gt;() .Fetch(x =&gt; x.CreatedBy) .Where(x =&gt; x.CreatedBy.Id == personId); </code></pre> <p>There's more reasons than just DDD purity to keep <code>person.CreatedOrders</code> out of your model. What if you have one person that places 10 orders a day, every day of the year, year after year? The first query almost certainly loads more data than you actually need. The second query, the one that doesn't need a <code>person.CreatedOrders</code> collection at all, gives you more control over which orders to fetch and how many to fetch.</p> <pre><code>var orders = session.Query&lt;OrderHeader&gt;() .Fetch(x =&gt; x.CreatedBy) .Where(x =&gt; x.CreatedBy.Id == personId) .Where(x =&gt; x.OrderDate &gt;= DateTime.Now.AddYears(-1)) .Skip(100) .Take(50); </code></pre> <p>Generally, if you find you're violating a DDD principle, it's usually a good indicator that you're doing something wrong, and you usually don't have to look too far to find other supporting evidence.</p> <p>Every once in a while, though, you do have to bend the rules a bit, and I think that's acceptable. For example, I usually try to just map one side of each relationship - that's all I really need from a DDD perspective. When referencing other aggregate roots, that usually means just modeling the <code>many-to-one</code> side, and for references within an aggregrate root - from the root to its children, that usually means just modeling the <code>one-to-many</code> and leaving the <code>many-to-one</code> out of the model. That would mean leaving <code>OrderItem.OrderHeader</code> out of the model.</p> <p>What if you needed to find out how much of a particular product had been sold, but only for Orders that have been Submitted? The easiest way to do this would be like so:</p> <pre><code>var quantitySold = session.Query&lt;OrderItem&gt;() .Where(x =&gt; x.Product.Id == productId &amp;&amp; x.OrderHeader.Submitted) .Sum(x =&gt; x.Quantity); </code></pre> <p>So in this case, we need to model both the <code>one-to-many</code> <code>orderHeader.OrderItems</code> and also the <code>many-to-one</code> <code>orderItem.OrderHeader</code>. This is because it is most efficient for this SUM to access the relevant OrderItems directly, rather than first go through <code>OrderHeader</code> as DDD would dictate. I'm OK with that.</p> <h3>Left outer joins on un-mapped relationships</h3> <p>Ignoring the DDD part of the question, this LEFT OUTER JOIN can be simulated by combining the results of two separate queries - one to get the orders...</p> <pre><code>var orders = session.Query&lt;OrderHeader&gt;() .Fetch(x =&gt; x.CreatedBy); </code></pre> <p>... and another to get the people that have no orders:</p> <pre><code>var peopleWithNoOrders = session.Query&lt;Person&gt;() .Where(p =&gt; !session.Query&lt;OrderHeader&gt;().Any(o =&gt; o.CreatedBy == p)); </code></pre>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

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