LINQ參數過多時的解決方案

來源:互聯網
上載者:User

在項目中曾有這樣的應用,許可權篩選時先組織出員工的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])
    )

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.