我正在扩展 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: could not execute query [ 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 中的函数调用将 @p1=1 作为第三个参数,并且 WHERE 子句是内联 CASE 而不是
dbo.f_documentsfreetextsearch(document0_.IDDOCUMENT, @p0, @p1) = 1
正如我所料。
如果我在我的 C# 代码中将 bool 参数和返回类型更改为 Int32,则一切正常(但仍然不是很优雅)。
知道如何使所需的语法起作用吗?
提前致谢
克劳迪奥
PS:抱歉有很多代码和错误的文字:P