NHibernate IN表达/限制达到2100参数限制SQL Server

问题描述 投票:0回答:2

是否有一种方法可以强制NHibernate运行查询而不将其作为参数化查询执行。基本上,我遇到了一个问题,我达到了SQL Server的2100参数限制。

由于查询的“ IN”限制,我达到了极限。由于某些原因,我将不涉及有关需要在查询中使用NHibernate In Restriction的详细信息。

Query.Add(Restrictions.In("df.ID", myList));

我已经在查询上运行NHibernate Profiler,并且NHibernate将每个“ In”值作为参数而不是文字值传递。

myList是一个具有超过5201个值的数组。我已经在线研究过,可以传递给SQL的IN值没有限制,因此,如果我可以让NHibernate将这些值作为文字值而不是应该解决我的参数的值来传递。

任何帮助将不胜感激。另外,请不要对我使用IN语句发表评论,我遇到了一个问题,我的查询要求我以这种方式使用IN语句,而我无法以其他任何方式使用它。

sql asp.net sql-server nhibernate linq-to-nhibernate
2个回答
1
投票

我能够通过使用添加到查询中的SQL Criterion语句并使用表值参数来解决此问题。

而不是这个:

Query.Add(Restrictions.In("df.ID", myList));

我使用过:

Query.Add(new SQLCriterion(new SqlString(string.Format("this_.ID NOT IN (SELECT * FROM [dbo].[Explode] ('{0}'))", siteProdIds)), new object[0], new IType[0]))

然后我在数据库上创建了此函数:

CREATE FUNCTION [dbo].[Explode](
    @string    varchar(MAX) -- '1,2,3,5,6,7'
)
RETURNS @table TABLE(element int)
AS
BEGIN
DECLARE @temp varchar(MAX), @delimPos AS tinyint = 0         
SET @temp= LTRIM(RTRIM(@string))
WHILE CHARINDEX(',',@temp) > 0 
BEGIN 
SET @delimPos = CHARINDEX(',',@temp)
INSERT INTO @table(element) VALUES (CAST((LEFT(@temp,@delimPos-1)) AS int))
SET @temp= RTRIM(LTRIM(SUBSTRING(@temp,@delimPos+1,LEN(@temp)-@delimPos))) 
END 
INSERT INTO @table(element) VALUES (CAST((@temp) AS int))
RETURN
END

0
投票

如果可以使用文字值,则可以使用以下类:

    /// <summary>
    /// IN expression with inlined parameters like  "Id IN (1, 2, 3)"   
    /// </summary>
    public class InlineInExpression : SimpleExpression
    {
        //Note!!! this works properly only for numeric types. String list requires escaping and wrapping each value in `[escapedValue]`
        public static InlineInExpression For<T>(string propertyPath, IEnumerable<T> list)
        {
            return new InlineInExpression(propertyPath, string.Join(", ", list));
        }

        /// <summary>
        /// IN expression ctor
        /// </summary>
        /// <param name="propertyPath">Property path</param>
        /// <param name="inExpression">Coma-delimited parameters like "1, 2, 3"</param>
        private InlineInExpression(string propertyPath, string inExpression)
            :base(propertyPath, null, inExpression)
        {
        }

        public override SqlString ToSqlString(ICriteria criteria, ICriteriaQuery criteriaQuery)
        {
            SqlString[] columnNames =
                CriterionUtil.GetColumnNamesForSimpleExpression(PropertyName, null, criteriaQuery, criteria, this, Value);

            if (columnNames.Length != 1)
                throw new HibernateException("This expression supports only single column properties.");

            return new SqlString(columnNames[0], " IN (", Op, ")");
        }
    }

用法示例:

Query.Add(InlineInExpression.For("df.ID", myList));

请注意,它仅适用于数字值(整数,长整数等)。如果需要字符串处理-您应该自己实现。

您还可以使这种方法适应您的解决方案,以避免将SQLCriterion与表别名和列名一起使用。

© www.soinside.com 2019 - 2024. All rights reserved.