1

私は NHibernate Linq プロバイダーを拡張しており、ビット パラメーターと戻り値の型の両方を持つユーザー定義を呼び出したいと考えています。

SQL ユーザー定義関数のシグネチャは次のとおりです。

 FUNCTION f_DocumentsFreeTextSearch
 (
     @docId int,
     @searchString varchar(8000),
     @searchTitle bit
 )
 RETURNS bit

Linq の使用に使用される「偽の」拡張メソッドは次のとおりです。

public static class DialectExtensions
{
    public static bool FreeText(this Document doc, string searchString, bool searchTitle)
    {
        return false;
    }
}

これが私のLinqToHqlGeneratorsRegistryです

public sealed class ExtendedLinqToHqlGeneratorsRegistry : DefaultLinqToHqlGeneratorsRegistry
{
    public ExtendedLinqToHqlGeneratorsRegistry()
    {
            DialectExtensions.FreeText(null, null, true)),
            new FreeTextGenerator());
    }
}

そして、ここに私のジェネレーターがあります:

public class FreeTextGenerator : BaseHqlGeneratorForMethod
{
    public FreeTextGenerator()
    {
        SupportedMethods = new[]
                               {
                                   ReflectionHelper.GetMethodDefinition(() => DialectExtensions.FreeText(null, null, true))
                               };
    }

    #region Overrides of BaseHqlGeneratorForMethod

    public override HqlTreeNode BuildHql(MethodInfo method, Expression targetObject, ReadOnlyCollection<Expression> arguments, HqlTreeBuilder treeBuilder, IHqlExpressionVisitor visitor)
    {
        return treeBuilder.MethodCall("dbo.f_documentsfreetextsearch", arguments.Select(a => visitor.Visit(a).AsExpression()).ToArray());
    }

    #endregion
}

これは望ましい使用法です:

    [TestMethod]
    public void CanFreeText()
    {
        var query = SessionHolder.Current.Query<Document>();
        var list = query.Where(d => d.FreeText("giorno", true)).ToList();            
    }

最初の問題: 上記のコードは InvalidCastException を引き起こします:

テスト メソッド App.Tests.NHMapping.CanFreeText が例外をスローしました: System.InvalidCastException: タイプ 'NHibernate.Hql.Ast.HqlMethodCall' のオブジェクトをタイプ 'NHibernate.Hql.Ast.HqlBooleanExpression' にキャストできません。

この方法で解決しました(エレガントではありませんが、機能します):

    [TestMethod]
    public void CanFreeText()
    {
        var query = SessionHolder.Current.Query<Document>();
        var list = query.Where(d => d.FreeText("giorno", true) == true).ToList();            
    }

NHibernate はクエリを実行しますが、生成された SQL は間違っています。

テスト メソッド App.Tests.NHMapping.CanFreeText が例外をスローしました: NHibernate.Exceptions.GenericADOException: クエリを実行できませんでした [select [...] from dbo.DOCUMENTS document0_ where case when dbo.f_documentsfreetextsearch(document0_.IDDOCUMENT, @p0, @p1 =1) then 1 else 0 end=@p2 ] Name:p1 - Value:giorno Name:p2 - Value:True Name:p3 - Value:True [SQL: select [...] from dbo.DOCUMENTS document0_ where case when dbo.f_documentsfreetextsearch(document0_.IDDOCUMENT, @p0, @p1=1) then 1 else 0 end=@p2] ---> System.Data.SqlClient.SqlException: '=' 付近の構文が正しくありません。

生成された SQL の関数呼び出しには、3 番目のパラメーターとして @p1=1 があり、WHERE 句はインライン CASE ではなくインライン CASE であることに注意してください。

dbo.f_documentsfreetextsearch(document0_.IDDOCUMENT、@p0、@p1) = 1

私の期待通りに。

C# コードで bool パラメーターを変更し、戻り値の型を Int32 にすると、すべてがうまく機能します (ただし、まだあまりエレガントではありません)。

目的の構文を機能させる方法について何か考えはありますか?

前もって感謝します

クラウディオ

PS: たくさんのコードとエラーのテキストで申し訳ありません:P

4

1 に答える 1

1

boolean プロパティに usertype を使用したときと同じバグ NH-2839に遭遇したようです。これが修正されるまで、今できることはあまりありません。

于 2012-09-05T18:33:22.800 に答える