Oracle で、列の部分文字列部分を値のリストと一致させる必要があるシナリオがありました。必要な列に部分文字列を適用するために sqlfunction プロジェクションを使用していましたが、そのプロジェクションを句内制限の一部として追加しました。以下は、私がそのために書いた単純化された基準です。
ICriteria criteriaQuery = session.CreateCriteria<Meeting>()
.Add(Restrictions.In(
Projections.SqlFunction(
"substring",
NHibernateUtil.String,
Projections.Property("Code"),
Projections.Constant(1),
Projections.Constant(3)),
new string[] { "D01", "D02" }))
.Add(Restrictions.In("TypeId", meetingTypes));
これで私が抱えていた問題は、生成された SQL が間違っていたことです。ステートメントに登録されたパラメーターの数が、ステートメントが実際に使用する数よりも多く、使用されていないにもかかわらず、一部のパラメーターが繰り返されていました。これにより、ステートメントがメッセージ「ORA-01036: 不正な変数名/番号」で失敗します。生成されたクエリ
SELECT this_.Meeting_id as Meeting1_0_2_, .....
WHERE substr(this_.Mcs_Main, :p0, :p1) in (:p2, :p3)
and this_.Meeting_Type_Id in (:p4, :p5);
:p0 = 1, :p1 = 3, :p2 = 1, :p3 = 3, :p4 = 'D02', :p5 = 'D03', :p6 = 101, :p7 = 102
p2 と p3 が再度生成され、p0 と p1 の複製であり、クエリ全体が失敗するためです。
新しいプロパティを式でマッピングすることでこれを一時的に解決できましたが、部分文字列を評価する必要がない場合でも式が常に実行されるため、これは正しいアプローチではないと思います。
In 句の組み合わせで使用した場合に射影が正常に機能するかどうかについての提案は、In ではなく Equal Restriction を使用すると、同じ射影が正常に機能します。