I am trying to get a parent entity where all entities in a child collection are in another list.
For example:
public class Parent {
public virtual int Id {get;set;}
public virtual List<Child> Children {get;set;}
}
public class Child {
public virtual int Id {get;set;}
public virtual string Name {get;set;}
}
I’ve tried various combinations of Joins and Restrictions but can’t seem to hit the spot.
So please help with suggestions.
Current example below:
public IList<Lead> GetAllAvailable(string[] names)
{
var result = Session.CreateCriteria<Parent>()
.CreateCriteria("Children")
.Add(Expression.In("Name", names)).List<Parent>();
return result;
}
Edit:
This is the sql equivilent:
select *
from dbo.Parent
join ( select p.id
from dbo.Parent p
join dbo.ParentToChildren on p.Id = dbo.ParentsToChildren.Parent_Id
join dbo.Child on dbo.ParentToChildren.Child_Id = dbo.Child.Id
where Name in ( 'foo', 'bar' )
group by p.Id
having count(1) > 1
) as foo on dbo.Parent.Id = foo.Id
Here’s my suggestion:
The idea is as follows: find all children that have a
Namelike one of thenamesentries. Group those children by theirParent. YourChildwill need aParentproperty mapped to the respective parent for this, but that’s a good idea anyway. For all groups with a size equal to (or greater than, but that shouldn’t happen, so you could replaceGewithEq)names.Length, return their parent; because if the size of the group is equal tonames.Length, all names have been found assuming no two children of a parent have the same name.The generated query:
I’ve created a test app that returned promising results.
If you need to do more with the parents, like paging or fetching the children, you could split this problem into a sub query (note that the
.Fetch(x=>x.Children).Eagerline is not required, it’s just an example what you can further do with the query):SQL (without the
Fetch):Update:
If Parent<->Child is many-to-many, things get a little bit trickier:
The main difference is that instead of grouping by the direct
Parentproperty ofChildI first needed to join the parents collection. To reference each parent there I introduce an aliasparent.The generated SQL is pretty close to the original approach:
For my test scenario it works, so hopefully it will for you, too.