我正在扩展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