如何绕过Linq-to-SQL中的参数限制.Contains

时间:2015-03-31 15:25:44

标签: sql-server linq-to-sql

我有一个耗时的Linq-to-SQL查询,它看起来像:database.GetTable<....>().Where(.....).Join(.......).Join(.......).Join(........).Select(a => new XResult(.......)).ToArray()。它工作得很慢,我试图通过将所有XResult缓存到static List来加快速度。

为此,我在查询序列中添加了.Where(a => !cachedResults.Contains(a)),但我遇到了问题:"The incoming tabular data stream (TDS) remote procedure call (RPC) protocol stream is incorrect. Too many parameters were provided in this RPC request. The maximum is 2100."

那么......是否有可能重新设计我的查询以绕过SQL中的参数限制?也许临时表?或者以某种方式重新设计缓存机制?有什么想法吗?

更新:我尝试将所有缓存的XResult合并为字符串,然后执行.Where(a => SqlMethods.Like(mergedResults, "%|" + a.Id.ToString() + "|%")).。它不会崩溃,也许它甚至可以工作,但我无法得到结果 - 我得到了SQL超时。所以......这不是可接受的解决方案。还有其他想法吗?

1 个答案:

答案 0 :(得分:0)

我的最终解决方案。

在数据库创建表值函数中,它接收合并的id为VARBINARY(MAX),将它们拆分并返回INT s的表:

CREATE FUNCTION [dbo].[SplitIds]
(   
    @data VARBINARY(MAX)
)
RETURNS @result TABLE(Id INT)
AS
BEGIN
    IF @data IS NULL
        RETURN 
    DECLARE @ptr INT = 0, @size INT = 4
    WHILE   (@ptr) * @size < LEN(@data)
    BEGIN
        INSERT INTO @result(Id)
        VALUES(SUBSTRING(@data, (@ptr* @size) + 1, @size))
        SET @ptr += 1
    END
    RETURN
END

将其从服务器资源管理器拖到DBML设计器。

在Linq-to-SQL序列中使用它,就像任何其他内置方法一样,例如我使用它如下:database.GetTable<....>().Join(database.SplitIds(ConvertIdsToBinary(Ids)), ......).Where(.....).Join(.......).Join(.......).Join(........).Select(a => new XResult(.......)).ToArray()