5

NHibernateのCriteriaAPIを使用して、これに相当するものを記述しようとしています。

select foo_id from foo_history
group by foo_id
having sum(bar_in) > 0 or sum(baz_in) > 0;

このマッピングで:

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="MVC"
                   namespace="MVC.Model.Things">
  <class name="MVC.Model.Things.FooHistory, MVC"
         table="foo_history">
    <id name="ID" column="foo_hist_id" type="guid"
        unsaved-value="00000000-0000-0000-0000-000000000000">
      <generator class="guid.comb" />
    </id>

    <!-- Properties -->
    <property name="BarIn" column="bar_in" type="decimal"
              precision="19" scale="4" not-null="true" />
    <property name="BazIn" column="baz_in" type="decimal"
              precision="19" scale="4" not-null="false" />

    <!-- Foreign Keys -->
    <many-to-one name="Foo" column="foo_id"
                 class="MVC.Model.Things.Foo, MVC.Model.Things"
                 not-null="true" />
  </class>
</hibernate-mapping>

およびこの基準コード(サブクエリになるため、切り離されています):

var results = DetachedCriteria.For<FooHistory>("fh")
    .SetProjection(Projections.ProjectionList()
        .Add(Projections.GroupProperty(Projections.Id()))
        .Add(Projections.Sum("fh.BarIn"))
        .Add(Projections.Sum("fh.BazIn")))
    .Add(Restrictions.Gt(Projections.Sum("fh.BarIn"), 0) ||
        Restrictions.Gt(Projections.Sum("fh.BazIn"), 0))
    .GetExecutableCriteria(session).List();

SetProjection()問題は、NHibernateが無効なMySQLを生成する結果の後に条件付き制限を追加することです。

SELECT this_.foo_hist_id as y0_,
       sum(this_.bar_in) as y1_,
       sum(this_.baz_in) as y2_
FROM foo_history this_
WHERE (sum(this_.bar_in) > ?p0
       or sum(this_.baz_in) > ?p1)
GROUP BY this_.foo_hist_id

...HAVINGの代わりにWHEREを使用します。単一の制限を使用すると正常に機能し、すべてが正しくなります。HN-1280( "CreateCriteriaクエリにHAVINGサポートを追加し、パラメーターの順序のバグを修正する")なので、これは可能だと思いますが、正しい "OR"言語を使用していません(たとえば、Restrictions.Disjunction()常にWHEREを作成します)。

これは可能ですか?

4

1 に答える 1

2

私はこの問題に直面しましたが、ページネーションに ToRowCountQuery() が必要な場合などに機能しないため、私の回避策は適切ではなかったと思います。とにかく...組み込みのOrExpressionの代わりにこのクラスを使用できます

class OrHaving : OrExpression
    {
        public OrHaving(ICriterion lhs, ICriterion rhs) : base(lhs, rhs)
        {
        }

        public override IProjection[] GetProjections()
        {
            return LeftHandSide.GetProjections().Concat(RightHandSide.GetProjections()).ToArray();
        }
    }

お気に入り

.Add(new OrHaving (Restrictions.Gt(Projections.Sum("fh.BarIn"), 0) ,
                   Restrictions.Gt(Projections.Sum("fh.BazIn"), 0)))
于 2012-12-22T19:40:34.730 に答える