Nhibernate count distinct (based on multiple columns)

杀马特。学长 韩版系。学妹 提交于 2019-12-03 18:10:00

问题


Basically, i have been trying to do this (count distinct based on two columns):

select count(distinct(checksum(TableA.PropertyA, TableB.PropertyB))) 
from TableA 
left outer join TableB
on TableA.TableBId = TableB.Id 
where PropertyA like '%123%'

Been googling on how to do this but with no luck. Tried this, but never actually worked. This does not count distinctly based on the two properties from two tables:

var queryOver = c.QueryOver<TableA>();
TableB tableBAlias = null;
TableA tableAAlias = null;
ProjectionList projections = Projections.ProjectionList();

queryOver.AndRestrictionOn(x => x.PropertyA).IsLike("%123%");
projections.Add(Projections.CountDistinct(() => tableAAlias.PropertyA));

queryOver.JoinAlias(x => x.TableB , () => tableBAlias, JoinType.LeftOuterJoin);
projections.Add(Projections.CountDistinct(() => tableBAlias.PropertyB));

queryOver.Select(projections);
queryOver.UnderlyingCriteria.SetProjection(projections);
return queryOver.TransformUsing(Transformers.DistinctRootEntity).RowCount();

回答1:


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 checksum1:

  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)"));
        }
    }
    
  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>());
    
  3. 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);   
        }
    }
    
  4. 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 */
    


1Still trying to figure out if there's a way to map a function without manually specifying the number of arguments

来源:https://stackoverflow.com/questions/21725327/nhibernate-count-distinct-based-on-multiple-columns

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!