views:

47

answers:

2

Hi all,

say that we have 2 entity EntityA and EntityB , with the related tables, TableA and TableB.

i have to implement this query:

select a.Id , (select count(b.Id) from TableB b where b.FKa = a.Id and b.AnotherField > 0) as TheCount
from TableA a 

i'm very close to that since i wrote this code:

var subCrit = DetachedCriteria.For<EntityB>
                                        .Add<EntityB>(e => e.AnotherField > 0)
                                        .SetProjection(LambdaProjection.Count<EntityB>(e => e.Id).As("TheCount"));

var crit = Session.CreateCriteria<EntityA>
                        .SetProjection(LambdaProjection.GroupProperty<EntityA>(e => e.Id).As("Id),
                                            Projections.SubQuery(subCrit));

if i execute this criteria i obtain the following SQL:

select a.Id as Id , (select count(b.Id) from TableB b where b.AnotherField > 0) as TheCount from TableA a

as u can see , it's very close to what i'm trying to achieve...the problem (and it's definetely a big problem :D) is that theres no link between the subquery and the entities of TableA ( where b.FKa = a.Id ). I cant find a way to correlate the subquery to the external query via criteria.

Any suggestions ?

Ta a lot

Alessandro

EDIT:

changing the point of view i also could do something like that:

 var crit = Session.CreateCriteria<EntityA>()
                   .CreateAlias<EntityB>(a => a.B, () => b);
                   .SetProjection(LambdaProjection.Count<A>(a => b.Id).As("TheCount"),
                   .SetProjection(LambdaProjection.GroupProperty<EntityA>(a => a.Id));

and this is generating the following sql:

select count(b.Id) as TheCount, a.Id as IDa
from TableA a left outer join TableB b
on a.Id = b.FKa
group by a.Id

but here you can see that the additional where clause b.AnotherField > 0 is missing , and i dont know how to insert it just for the count.

Hope it's clear , thanks again

A: 

My suggestion is to change the SQL Statement

SELECT a.is, count(a.id) FROM TableA a JOIN TableB b ON a.id = b.fka AND b.af > 0 GROUP by a.ID

And create for it easy criteria.

Vash
Unfortunately i cannot change the sql statement as u suggested becuase in the same sql statement i have to return all the rows of TableA , not only the ones with the additional where clause..at the same time i have to count only the rows that satisfies that where clause. that's the why of the subquery for the count.
Alessandro Di Lello
edited the main post with another possible scenario
Alessandro Di Lello
If You add the restriction to aliased b is should work.
Vash
unfortunately not..cause if you add the restrictions to the aliased b , that restriction will be added in the where clauses .. what i want is to have a conditional count...and fortunately i found the working solution :) i'll post it in a few mins
Alessandro Di Lello
+2  A: 

Here is the solution:

var condition = Expression.Gt("b.AnotherField",0);
var conditionalProjection = Projections.Conditional(condition, Projections.Constant(1), Projections.Constant(0));

crit = Session.CreateCriteria<EntityA>()
                   .CreateAlias<EntityB>(a => a.B, () => b);
                   .SetProjection(Projections.Count(conditionalProjection).As("TheCount"),
                     (LambdaProjection.GroupProperty<EntityA>(a => a.Id));

and this is the sql generated:

select count(case b.AnotherField > 0 then 1 else 0 end) as TheCount , a.Id from TableA a inner join TableB b

hope it can be useful

cheers

Alessandro

enter code here
Alessandro Di Lello