一尘不染

Nhibernate计数不同(基于多个列)

sql

基本上,我一直在尝试执行此操作(基于两列的计数不同):

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

一直在搜寻如何执行此操作,但是没有运气。尝试过此方法,但从未真正起作用。根据两个表的两个属性,这并没有明显的不同:

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();

阅读 241

收藏
2021-03-10

共1个答案

一尘不染

好的,这将采取一些步骤,请多多包涵。我在这里假设使用SQL Server,但说明应适用于支持checksum1的任何方言:

  1. 创建支持该checksum功能的自定义方言:

    public class MyCustomDialect : MsSql2008Dialect
    

    {
    public MyCustomDialect()
    {
    RegisterFunction(“checksum”, new SQLFunctionTemplate(NHibernateUtil.Int32, “checksum(?1, ?2)”));
    }
    }

  2. 更新配置以使用自定义方言(您可以在配置XML文件中或使用代码来执行此操作。有关更多信息,请参见此答案。这是我在现有配置代码中执行的操作:

    configuration
    .Configure(@"hibernate.cfg.xml")
    .DataBaseIntegration(
        db => db.Dialect<MyCustomDialect>());
    
  3. 创建一个调用的自定义投影checksum。此步骤是可选的-您可以根据需要Projections.SqlFunction直接调用,但是我认为将其重构为一个单独的函数更为简洁:

    public static class MyProjections
    

    {
    public static IProjection Checksum(params IProjection[] projections)
    {
    return Projections.SqlFunction(“checksum”, NHibernateUtil.Int32, projections);
    }
    }

  4. 编写您的QueryOver查询并调用自定义投影:

    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>();
    

这应该生成看起来像您所追求的SQL:

    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 */

1仍在尝试找出是否有一种方法可以在不手动指定参数数量的情况下映射函数

2021-03-10