LINQ参数过多时的解决方案

<script type="text/JavaScript"> </script> <script src="http://a.alimama.cn/inf.js" type="text/javascript"></script>

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

 

int [] inputList  =   new   int [ 2100 ];
            
for  ( int  i  =   0 ; i  <  inputList.Length; i ++ )
            {
                inputList[i] 
=  i;
            }
            DataClasses1DataContext dc 
=   new  DataClasses1DataContext();
            var t
= (from x  in  dc.test1
                  select x).Where(c
=> 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 < T >  test < T > ()
        {
            DataClasses1DataContext dc 
=   new  DataClasses1DataContext();
            dc.Log 
=  Console.Out;
            
int [] inputList  =   new   int [ 2100 ];
            StringBuilder sqlstr 
=   new  StringBuilder( " select * from  " );
            sqlstr.Append(
typeof (T).Name);
            sqlstr.Append(
"  where testid in ( " );
            
for  ( int  i  =   0 ; i  <  inputList.Length; i ++ )
            {
                sqlstr.Append(i);
                
if  (i  <  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
< T >  t  =  dc.Translate < T > (dr).ToList();
            
return  t;
        }
static   void  Main( string [] args)
        {
        List
< test1 >  l  =  MyClass.test < test1 > ();
            
foreach  (var item  in  l)
            {
                Console.WriteLine(item.testID);
            }

}

 

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

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

 

var tt  =  (from x  in  dc.test
                       select x.testid);
            var t 
=  from x  in  dc.log
                    
where  tt.Contains < int ?> (x.logId)
                    select x;

            dc.Log 
=  Console.Out;
            
foreach  (var item  in  t)
            {
                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 <script type="text/JavaScript"> </script> <script src="http://a.alimama.cn/inf.js" type="text/javascript"></script>

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值