我试图找到一种方法使NHibernate(sp_executesql
)发送的执行查询到数据库以使用自定义sql数据类型。我在C#中获得了Linq表达式,我尝试运行并使用自定义HqlGenerator来支持IsDescendantOf
的{{1}}方法。
HierarchyId的我的C#属性当前被表示为字符串(不需要HierarchyId
表示的复杂性。)
但问题是发送到Microsoft.SqlServer.Types
的结果字符串表明传递的参数是sp_executesql
,无论我根据映射改变了什么。但这导致我的NVARCHAR(400)
字段的索引出现问题,查询超时,因为它根本没有使用我的索引。但是只要我将参数类型更改为HierarchyId
,它就会在0到1秒内运行。因此,我试图找到一种方法来获取HierarchyId
语句来指定发送的参数是sp_executesql
而不是HierarchyId
。
我尝试更改映射中的类型,我尝试在映射中更改自定义SqlType。我不确定如何影响NHibernate以手动指定调用NVARCHAR(4000)
的类型。
此时我真的需要一个解决方案,但我不确定NHibernate的内部如何确定参数的类型。
已更新为代码
C#代码 我正在处理的场景的简化表达式
sp_executesql
我的ClaimSubmission类上的Hierarchy属性是一个字符串字段。使用var currentUserScopedHierarchy = "/11/";
session.Query<ClaimSubmission>()
.Where(x => x.Hierarchy.IsDescendantOf(currentUserScopedHierarchy))
.OrderByDescending(x => x.DateCreated).ToList();
HqlGenerator
,SQL Server Profiler中观察到的SQL如下所示
SQL
IsDescendantOf
问题在于最后一位参数的值为&#34; / 11 /&#34;正在作为exec sp_executesql N'/* [expression] */select claimsubmi0_.ObjectId as ObjectId22_,
claimsubmi0_.DateCreated as DateCrea2_22_,
claimsubmi0_.DateModified as DateModi3_22_,
claimsubmi0_.Name as Name22_,
claimsubmi0_.SearchText as SearchText22_,
claimsubmi0_.CreatedBy as CreatedBy22_,
claimsubmi0_.ModifiedBy as ModifiedBy22_,
claimsubmi0_.OwnerId as OwnerId22_,
claimsubmi0_.Hierarchy as Hierarchy22_,
claimsubmi0_.TypeId as TypeId22_,
claimsubmi0_.Terminate as Terminate22_
from PseudoObjects claimsubmi0_
where /* removed extra code here that delt with discriminators that isn't relevant */
claimsubmi0_.Hierarchy.IsDescendantOf(@p0) = 1
order by claimsubmi0_.DateCreated desc'
,N'@p0 nvarchar(4000)' ,@p0=N'/11/'
传递。这样,这个查询大约需要20秒(30+一次我添加回其他逻辑,我删除了以获得更简化的示例),这是因为数据类型导致它忽略我的索引。如果我将类型更改为NVARCHAR(400)
,则查询是即时的。如果我在调用HierarchyId
的同时运行查询并内联参数值,那么它也是即时的。
HqlGenerator相关
扩展方法
sp_executesql
如果它是相关的,那么这里也是HqlGenerator
public static bool IsDescendantOf(this string childHierarchy, string parentHierarchy)
{
return childHierarchy.StartsWith(parentHierarchy);
}
作为NHibernate设置的一部分,我有这个
public class IsDescendantOfGenerator : BaseHqlGeneratorForMethod
{
public IsDescendantOfGenerator()
{
SupportedMethods = new[]
{
ReflectionHelper.GetMethodDefinition(() => ExtensionMethods.IsDescendantOf(null, null))
};
}
public override HqlTreeNode BuildHql(MethodInfo method, Expression targetObject, ReadOnlyCollection<Expression> arguments, HqlTreeBuilder treeBuilder, IHqlExpressionVisitor visitor)
{
return treeBuilder.BooleanMethodCall("_IsDescendantOf", new[] { visitor.Visit(arguments[0]).AsExpression(), visitor.Visit(arguments[1]).AsExpression() });
}
}