I hope I understood your issue correctly, so you just want to get all Authors which have at least one paper which has this flag set to true, right?
Why do you not just use Linq, its way easier to write and should work for such simple scenarios.
I would also map your flag to a bool, so I guess there is no need to do a Max
operation at all...
Example:
var authorsWithPublications = session.Query<Paper>()
.Select(p => new { Author = p.Author, HasPublished = p.HasPublished })
.Where(p => p.HasPublished == true).ToList();
I used this simple scenario, let me know if this doesn't match your issue:
Entity + Mapping:
public class Paper
{
public virtual int Id { get; set; }
public virtual string Author { get; set; }
public virtual bool HasPublished { get; set; }
public virtual string Description { get; set; }
public virtual string Something { get; set; }
public virtual string SomethingElse { get; set; }
}
public class PaperMap : ClassMap<Paper>
{
public PaperMap()
{
Id<int>("Id");
Map(p => p.Author);
Map(p => p.HasPublished);
Map(p => p.Description);
Map(p => p.Something);
Map(p => p.SomethingElse);
}
}
Creation of some test data and the query
using (var session = sessionFactory.OpenSession())
{
Random r1 = new Random();
for (int i = 0; i < 100; i++)
{
session.Save(new Paper()
{
Author = "Author" + i,
HasPublished = r1.Next(0, 2) == 0 ? false : true,
Description = "Description" +i,
Something = "Something" + i,
SomethingElse = "something else" + i
});
}
session.Flush();
var authorsWithPublications = session.Query<Paper>()
.Select(p => new { Author = p.Author, HasPublished = p.HasPublished })
.Where(p => p.HasPublished == true).ToList();
}
It actually returns me exactly those authors... You could process this further to have just a distinct result...
:edit starts:
to query all authors with the maximum value of the flag, it becomes a little bit tricky with linq, the following linq query would return that result:
var authorsWithPublications = session.Query<Paper>()
.GroupBy(p => new { Author = p.Author })
.Select(p => new {
Author = p.Key,
HasPublished = p.Max(c=> c.HasPublished)
})
.ToList();
But if c.HasPublished is a bit field in SqlServer, it will give you the sql exception that max is not allowed on bit fields.
Trying to convert the bool to int wihtin the linq statement like
...HasPublished = p.Max(c => c.HasPublished == true ? 1 : 0)
will throw an exception Code supposed to be unreachable
, because it is not supported by nHibernate...
The only way I found to get the first Linq query running is by specifying a formula within the mapping:
Map(p => p.HasPublished).Formula("cast (HasPublished as int)");
Now this formula will be applied to all select statements, statement will look like this:
select paper0_.Author as col_0_0_, max(cast (paper0_.HasPublished as int)) as col_1_0_
from [Paper] paper0_
group by paper0_.Author
Anyways you already found the solution and the following does actually the same without the need of a formula
var criteria = session.CreateCriteria<Paper>();
criteria.SetProjection(
Projections.Group<Paper>(p=>p.Author),
Projections.Max(
Projections.Cast(NHibernateUtil.Int32, Projections.Property("HasPublished")))
);
var result = criteria.List();
But maybe we both learned something ;)