2015-03-31 113 views
0

我有一个耗时的Linq-to-SQL查询,如下所示:database.GetTable<....>().Where(.....).Join(.......).Join(.......).Join(........).Select(a => new XResult(.......)).ToArray()。它工作得很慢,我试图通过将所有XResult缓存到static List来加速它。如何解决Linq-to-SQL中的参数限制.Contains

为此,我在查询序列中添加了.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中的参数限制问题?也许临时表?或者以某种方式重新设计缓存机制?有任何想法吗?

UPDATE:我试图合并所有缓存XResult s到字符串,然后做.Where(a => SqlMethods.Like(mergedResults, "%|" + a.Id.ToString() + "|%")).。它不会崩溃,甚至它可以工作,但我无法得到结果 - 我得到SQL超时。所以......这不是可接受的解决方案。任何其他想法?

+0

你能重新写你的查询在数据库中的存储过程或视图从前端调用? – Donal 2015-03-31 15:36:53

+0

我可以创建存储过程或视图,但它又会如何帮助我不将20000个参数传递给它? – Denis 2015-03-31 16:25:45

+0

一个解决方案是将参数作为单个参数传递给存储过程,即逗号分隔的参数串。 – Donal 2015-03-31 16:28:54

回答

0

我的最终解决方案。

在数据库中创建表值函数,它接收合并ID作为VARBINARY(MAX),并将它们拆分和收益INT的桌子:

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到SQL序列像任何其他内置的方法,例如我用它如下:database.GetTable<....>().Join(database.SplitIds(ConvertIdsToBinary(Ids)), ......).Where(.....).Join(.......).Join(.......).Join(........).Select(a => new XResult(.......)).ToArray()