Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>yesterday I was working on the similar problem. I had to select/load all parent-objects with exactly the given list of child-objects. I could solve this with the Criteria-API, with only one drawback (see *1 below).</p> <pre><code>public class Project { public virtual int ProjectId{get;set;} public virtual IList&lt;Part&gt; Parts{get;set;} ... } public class Part { public virtual int PartId{get;set;} public virtual Project Project{get;set;} // *1 this is the drawback: I need a public property for the ForegienKey from the child to the parent ... } </code></pre> <p>Here comes the Criteria:</p> <pre><code>DetachedCriteria top = DetachedCriteria.For&lt;Project&gt;(); foreach(Part part in searchedParts) { DetachedCriteria sub = DetachedCriteria.For&lt;Part&gt;(); sub.Add(Expresion.Eq("PartId",part.PartId)); sub.SetProjection("Project"); top.Add(Subqueries.PropertyIn("ProjectId",sub)); } </code></pre> <p>Back to your example: The SQL would look like this.</p> <pre><code>SELECT * FROM project WHERE projectid IN ( SELECT projectid FROM part WHERE partid = 1 /* @p0 */ ) AND projectid IN ( SELECT projectid FROM part WHERE partid = 2 /* @p1 */ ) </code></pre> <p>Basicaly I add for each child a subquery that checks for it's existance in the project and combine them with and, so only project with all that children will be selected.</p> <p>Greetings</p> <p>Juy Juka</p> <h1>Additional Uses</h1> <p>I wasn't finished with my code after this and if somone needs what I had to find out, I'll add it here. I hope the additional information belongs here, but I am not sure because it's my first post on stackoverflow.com</p> <p>For the following examples we need a more complex part-class:</p> <pre><code>public class Part { public virtual int PartId{get;set;} public virtual Project Project{get;set;} public virtual PartType PartType{get;set;} ... } public class PartType { public virtual int PartTypeId{get;set;} public virtual string Name{get;set;} ... } </code></pre> <p><strong>Different criterion on child-objects</strong></p> <p>It is possible to use the same code when you do not have the primarykey(s) of the searched parts, but would like to find the parts with other properties.</p> <pre><code>// I am asuming building-projects with houses, gardens, garages, driveways, etc. IEnumerable&lt;PartType&gt; searchedTypes = new PartType[]{housePart, gardenPart}; // could be a parameter or users choise or what ever DetachedCriteria top = DetachedCriteria.For&lt;Project&gt;(); foreach(PartType type in searchedTypes) { DetachedCriteria sub = DetachedCriteria.For&lt;Part&gt;(); sub.Add(Expresion.Eq("PartType",type)); // this is all that had to be changed. We could even use more complex operations with and, or, not, etc. sub.SetProjection("Project"); top.Add(Subqueries.PropertyIn("ProjectId",sub)); } </code></pre> <p>Expected SQL</p> <pre><code>SELECT * FROM project WHERE projectid IN ( SELECT projectid FROM part WHERE parttype = 1 /* @p0 // aka. housePart */ ) AND projectid IN ( SELECT projectid FROM part WHERE parttype = 2 /* @p1 // aka. gardenPart */ ) </code></pre> <p><strong>Excluding children</strong></p> <p>To negate this and search partens who do <em>not</em> have the searched children is easily done by using Subqueries.PropertyNotIn instead of Subqueries.PropertyIn.</p> <p><strong>Exactly/only the searched children</strong></p> <p>This was the tricky part I had to work on the longest time. I wanted parents with exactly the given list of parts. To stay with the building-project example: I am searching projects with a house-part and a guarden-part but no other parts</p> <pre><code>IEnumerable&lt;PartType&gt; searchedTypes = new PartType[]{housePart, gardenPart}; DetachedCriteria top = DetachedCriteria.For&lt;Project&gt;(); ICriterion notCriterion = null; foreach(PartType type in searchedTypes) { ICriterion subCriterion = Expresion.Eq("PartType",type); DetachedCriteria sub = DetachedCriteria.For&lt;Part&gt;(); sub.Add(subCriterion); sub.SetProjection("Project"); top.Add(Subqueries.PropertyIn("ProjectId",sub)); // I am collecting all valid criterions for child-objects and negate them subCriterion = Expresion.Not(subCriterion); notCriterion = notCriterion == null ? subCriterion:Expresion.And(notCriterion,subCriterion); } // with the negated criterions I exclude all parent-objects with an invalid child-object DetachedCriteria not = DetachedCriteria.For&lt;Part&gt;(); not.Add(notCriterion); sub.SetProjection("Project"); top.Add(Subqueries.PropertyNotIn("ProjectId",not)); </code></pre> <p>Expected SQL</p> <pre><code>SELECT * FROM project WHERE projectid IN ( SELECT projectid FROM part WHERE parttype = 1 /* @p0 // aka. housePart */ ) AND projectid IN ( SELECT projectid FROM part WHERE parttype = 2 /* @p1 // aka. gardenPart */ ) AND projectid NOT IN ( SELECT projectid FROM part WHERE NOT ( parttype = 1 /* @p2 // aka. housePart */ ) AND NOT ( parttype = 2 /* @p3 // aka. gardenPart */ ) ) </code></pre> <p>(More then one house and/or one guarden is possible, since no checkon "duplicated" entries is done)</p>
    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. 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.
    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