You can use projections to do this. Using the QueryOver API in 3.X it would look something like this (subquery in your case will be different, but not too far off):
var subquery = DetachedCriteria.For<ToppingUse> ("t")
.Add (Restrictions.EqProperty ("t.Pizza.Id", "p.Id"))
.SetProjection (Projections.Count ("Id"));
Pizza p = null;
var toppedPizzas = session.QueryOver<Pizza>(() => p)
.Select(Projections.Property(() => p.Id)
, Projections.Property(() => p.Sauce)
, Projections.Property(() => p.Crust)
, Projections.Alias(Projections.SubQuery(subquery), "ToppingCount"))
.List<object[]>(); //then you need to handle mapping on your own somehow (look into ResultTransformers if needed)
this translates to the following criteria:
var subquery = DetachedCriteria.For<ToppingUse> ("t")
.Add (Restrictions.EqProperty ("t.Pizza.Id", "p.Id"))
.SetProjection (Projections.Count ("Id"));
var toppedPizzas = session.CreateCriteria<Pizza>("p")
.SetProjection(Projections.Property("p.Id")
, Projections.Property("p.Sauce")
, Projections.Property("p.Crust")
, Projections.Alias(Projections.SubQuery(subquery), "ToppingCount"))
.List<object[]>();//then you need to handle mapping on your own somehow (look into ResultTransformers if needed)
You just need to make sure you use the same aliases within your subquery and outer query.