• LINQ参数过多时的解决方案


    在项目中曾有这样的应用,权限筛选时先组织出员工的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转换成相应的类。

    8月11日更新:

    如果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])
        )

  • 相关阅读:
    web component的理解
    cdn
    const 命令
    let 的含义,及let 与 var 的区别
    选择器
    Qt5:Qt中一些函数功能介绍
    给软件工程师自学的建议
    Qt5:渐变效果的实现
    Wayland软件库 :替代 X Window 的软件库
    Qt5:窗口各类位置
  • 原文地址:https://www.cnblogs.com/nuaalfm/p/1264796.html
Copyright © 2020-2023  润新知