c# - Restrict QueryOver by child collection using nHibernate -


i trying parent entity entities in child collection in 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 , restrictions can't seem hit spot.

so please 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 sql equivilent:

select  *    dbo.parent         join ( select   p.id                    dbo.parent p                         join dbo.parenttochildren on p.id = dbo.parentstochildren.parent_id                         join dbo.child on dbo.parenttochildren.child_id = dbo.child.id                   name in ( 'foo', 'bar' )                group p.id                having   count(1) > 1              ) foo on dbo.parent.id = foo.id 

here's suggestion:

var parents = session.queryover<child>()   .whererestrictionon(x => x.name).isin(names)   .select(projections.group<child>(x => x.parent))   .where(restrictions.ge(projections.count<child>(x => x.parent), names.length))   .list<parent>(); 

the idea follows: find children have name 1 of names entries. group children parent. child need parent property mapped respective parent this, that's idea anyway. groups size equal (or greater than, shouldn't happen, replace ge eq) names.length, return parent; because if size of group equal names.length, names have been found assuming no 2 children of parent have same name.

the generated query:

select     this_.parent y0_     child this_     this_.name in (         /*  */     ) group     this_.parent having     count(this_.parent) >= /* names.length */; 

i've created test app returned promising results.

if need more parents, paging or fetching children, split problem sub query (note .fetch(x=>x.children).eager line not required, it's example can further query):

var parentsubquery =   queryover.of<child>()     .whererestrictionon(x => x.name).isin(names)     .select(projections.group<child>(x => x.parent))     .where(restrictions.ge(projections.count<child>(x => x.parent), names.length));  var parents = session.queryover<parent>()    .fetch(x=>x.children).eager // not necessary, example   .withsubquery.whereproperty(x => x.id).in(parentsubquery )   .list(); 

sql (without fetch):

select     this_.id id1_0_     parent this_     this_.id in (         select             this_0_.parent y0_                     child this_0_                     this_0_.name in (                 /* names */             )         group             this_0_.parent         having             count(this_0_.parent) >= /* names.length */     ); 

update:

if parent<->child many-to-many, things little bit trickier:

      parent parent = null;       var parentsubquery = queryover.of<child>()         .whererestrictionon(x => x.name).isin(names)         .joinqueryover(x => x.parents, () => parent)         .where(restrictions.ge(projections.count(() => parent.id), names.length))         .select(projections.group(() => parent.id));        var parents = session.queryover<parent>()         .withsubquery.whereproperty(x => x.id).in(parentsubquery)         .list(); 

the main difference instead of grouping direct parent property of child first needed join parents collection. reference each parent there introduce alias parent.

the generated sql pretty close original approach:

select     this_.id id2_0_     parent this_     this_.id in (         select             parent1_.id y0_                     child this_0_         inner join             childtoparent parents3_                 on this_0_.id=parents3_.childid         inner join             parent parent1_                 on parents3_.parentid=parent1_.id                     this_0_.name in (                 /* names */             )         group             parent1_.id         having             count(parent1_.id) >= /* names.length */     ); 

for test scenario works, you, too.


Comments

Popular posts from this blog

jasper reports - Fixed header in Excel using JasperReports -

media player - Android: mediaplayer went away with unhandled events -

python - ('The SQL contains 0 parameter markers, but 50 parameters were supplied', 'HY000') or TypeError: 'tuple' object is not callable -