NHibernate 3.3 Linq使用位参数和位结果调用用户定义的函数

时间:2012-09-04 13:24:58

标签: linq nhibernate

我正在扩展NHibernate Linq提供程序,我希望调用一个具有位参数[s]和返回类型的用户。

这是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:无法执行查询[   从dbo.DOCUMENTS document0_中选择[...] where where when   dbo.f_documentsfreetextsearch(document0_.IDDOCUMENT,@ p0,@ p1 = 1)然后   1 else 0 end = @ p2]名称:p1 - 值:giorno名称:p2 - 值:True   名称:p3 - 值:True [SQL:从dbo.DOCUMENTS document0_中选择[...]   当dbo.f_documentsfreetextsearch(document0_.IDDOCUMENT,   @ p0,@ p1 = 1)然后1 else 0 end = @ p2] ---&gt;   System.Data.SqlClient.SqlException:'='附近的语法不正确。

请注意,生成的SQL中的函数调用将@ p1 = 1作为第三个参数,并且WHERE子句是内联CASE而不是

  

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

正如我所料。

如果我在C#代码中更改bool参数并将类型返回到Int32,那么一切都运行良好(但仍然不是很优雅)。

如何获得所需的语法?

提前致谢

克劳迪奥

PS:抱歉有很多代码和错误'文字:P

1 个答案:

答案 0 :(得分:1)

似乎你使用usertype作为布尔属性时所用的bug NH-2839。在修复之前,你现在无能为力。