Basically, i have been trying to do this (count distinct based on two columns):
select count(distinct(checksum(TableA.PropertyA, TableB.PropertyB)))
from Ta
Okay this is going to take a few steps, so bear with me. I'm assuming SQL server here, but the instructions should work for any dialect that supports checksum
1:
Create a custom dialect that supports the checksum
function:
public class MyCustomDialect : MsSql2008Dialect
{
public MyCustomDialect()
{
RegisterFunction("checksum", new SQLFunctionTemplate(NHibernateUtil.Int32, "checksum(?1, ?2)"));
}
}
Update your configuration to use the custom dialect (you can do this either in your configuration XML file or with code. See this answer for more information). Here's how I did it inside of my existing configuration code:
configuration
.Configure(@"hibernate.cfg.xml")
.DataBaseIntegration(
db => db.Dialect<MyCustomDialect>());
Create a custom projection that calls checksum
. This step is optional-- you can call Projections.SqlFunction
directly if you'd like, but I think refactoring it into a separate function is cleaner:
public static class MyProjections
{
public static IProjection Checksum(params IProjection[] projections)
{
return Projections.SqlFunction("checksum", NHibernateUtil.Int32, projections);
}
}
Write your QueryOver query and call the custom projection:
int count = session.QueryOver<TableA>(() => tableAAlias)
.Where(p => p.PropertyA.IsLike("%123%"))
.Left.JoinQueryOver(p => p.TableB, () => tableBAlias)
.Select(
Projections.Count(
Projections.Distinct(
MyProjections.Checksum(
Projections.Property(() => tableAAlias.PropertyA),
Projections.Property(() => tableBAlias.PropertyB)))))
.SingleOrDefault<int>();
This should generate SQL that looks like what you're after:
SELECT count(distinct checksum(this_.PropertyA, tableba1_.PropertyB)) as y0_
FROM [TableA] this_
left outer join [TableB] tableba1_
on this_.TableBId = tableba1_.Id
WHERE this_.PropertyA like '%123%' /* @p0 */