天天看点

LINQ参数过多时的解决方案

在项目中曾有这样的应用,权限筛选时先组织出员工的id,然后使用LINQ在相应的表中查询数据,条件是这些查询出来的数据的id必须在刚才权限筛选出来的id中,但是如果权限中的id太多,就会出现问题“传入的表格格式数据流(TDS)远程过程调用(RPC)协议流不正确。此 RPC 请求中提供了过多的参数。最多应为 2100”。我推断可能是SQLServer中使用参数不能超过2100的原因。以上描述请看下边的例子。

<a></a>

int[] inputList = new int[2100];

            for (int i = 0; i &lt; inputList.Length; i++)

            {

                inputList[i] = i;

            }

            DataClasses1DataContext dc = new DataClasses1DataContext();

            var t=(from x in dc.test1

                  select x).Where(c=&gt;inputList.Contains(c.testID));

            dc.Log = Console.Out;

            foreach (var item in t)

                Console.WriteLine(item.testID);

运行以上代码会报“传入的表格格式数据流(TDS)远程过程调用(RPC)协议流不正确。此 RPC 请求中提供了过多的参数。最多应为 2100”异常,如果将inputList数组大小改为5,执行的sql如下:

SELECT [t0].[testID], [t0].[testContent], [t0].[p]

FROM [dbo].[test1] AS [t0]

WHERE [t0].[testID] IN (@p0, @p1, @p2, @p3, @p4)

现在问题是如果超过2100个参数怎么办,我没想出用linq实现的好办法,这里使用了一个折中的办法

public static List&lt;T&gt; test&lt;T&gt;()

        {

            int[] inputList = new int[2100];

            StringBuilder sqlstr = new StringBuilder("select * from ");

            sqlstr.Append(typeof(T).Name);

            sqlstr.Append(" where testid in (");

                sqlstr.Append(i);

                if (i &lt; inputList.Length - 1)

                {

                    sqlstr.Append(",");

                }

                else

                    sqlstr.Append(")");

            }         

            SqlCommand cmd = new SqlCommand(sqlstr.ToString(), (SqlConnection)dc.Connection);

            dc.Connection.Open();

            SqlDataReader dr = cmd.ExecuteReader();

            List&lt;T&gt; t = dc.Translate&lt;T&gt;(dr).ToList();

            return t;

        }

static void Main(string[] args)

        List&lt;test1&gt; l = MyClass.test&lt;test1&gt;();

            foreach (var item in l)

}

这里利用了反射得到表名,然后利用Linq中的Translate方法将SqlDataReader转换成相应的类。

8月11日更新:

如果inputList不是一个数组而是一个IQueryable,直接用就没什么问题

var tt = (from x in dc.test

                       select x.testid);

            var t = from x in dc.log

                    where tt.Contains&lt;int?&gt;(x.logId)

                    select x;

                Console.WriteLine(item.logMessage);

拼接出的sql语句如下:

SELECT [t0].[logId], [t0].[logMessage], [t0].[x]

FROM [dbo].[log] AS [t0]

WHERE EXISTS(

    SELECT NULL AS [EMPTY]

    FROM [dbo].[test] AS [t1]

    WHERE [t1].[testid] = ([t0].[logId])

    )

本文转自 你听海是不是在笑 博客园博客,原文链接:http://www.cnblogs.com/nuaalfm/archive/2008/08/10/1264796.html  ,如需转载请自行联系原作者