传入的请求包含太多参数.服务器最多支持2100个参数

fre*_*hie 16 c# linq

我有这个看似简单的linq-to-sql查询,可以搜索多个列中的一些数据; 这样的事情:

List<long> TheTableIDs = list of IDs (sometimes more than 2100)

var QueryOutput = (from x in TheDataContext.SomeTable

                   where TheTableIDs.Contains(x.ID) &&

                   x.Col1.Contains(SomeString) || 
                   x.Col2.Contains(SomeString))

                   select x.ID).ToList();
Run Code Online (Sandbox Code Playgroud)

我得到的错误是这样的:

附加信息:传入的请求包含太多参数.服务器最多支持2100个参数.减少参数数量并重新发送请求.

解决这个问题的最佳方法是什么?

我环顾四周,找到的解决方案看起来像这样:

var QueryOutput = TheDataContext.SomeTable.AsEnumerable()

        .Join(TheTableIDs, x => x.LeadID, ci => ci, (x, ci) => x)

        .Where(x => SomeString.Contains(x.Col1) == true ||
                    SomeString.Contains(x.Col2) == true)

        .Select(x => x.ID).ToList();
Run Code Online (Sandbox Code Playgroud)

这编译并没有抛出任何异常,但似乎忽略了Where条款SomeString.Contains

使此查询有效的解决方案是什么?

谢谢.

小智 11

简单 - 只要TheTAbleID包含少于2100个ID,那么这样做是不合法的.

将表切成2000块,然后分别查询每个块,可能是多个线程.

  • 好,谢谢; 我最终拆分了我的列表并并行运行查询。 (2认同)
  • 我不明白“切桌子”是什么意思。 (2认同)

Rez*_*eza 6

SQL in语句中不支持超过2100个值,但是您可以在具有超过2100行的表中使用in,因此您可以将数据插入表中并更改查询以in从表中选择进行检查

例如

Create TempIDs (bigint ID, uniqueidentifier guid)
Run Code Online (Sandbox Code Playgroud)

guid列用于防止混合不同的用户数据

在你的代码中

Guid myKey = Guid.New();
List<long> TheTableIDs = list of IDs (sometimes more than 2100)
TheDataContext.TempIDs.InsertAllOnSubmit(TheTableIDs.select(i => new TempIDs{ID = i, Guid = mykey});
TheDataContext.SubmitChanges();

var QueryOutput = (from x in TheDataContext.SomeTable

                   where TheDataContext.TempIDs.Contains(x.ID) &&

                   x.Col1.Contains(SomeString) || 
                   x.Col2.Contains(SomeString))

                   select x.ID).ToList();
Run Code Online (Sandbox Code Playgroud)

同样,如果您可以从数据库中检索ID,则可以在sql中编写一个表值函数以返回ID并在代码中对该函数进行建模,假设其名称为fnGetIds。然后在您的代码中使用它,如下所示

var QueryOutput = (from x in TheDataContext.SomeTable

                   where TheDataContext.fnGetIds().Contains(x.ID) &&

                   x.Col1.Contains(SomeString) || 
                   x.Col2.Contains(SomeString))

                   select x.ID).ToList();
Run Code Online (Sandbox Code Playgroud)

  • @frenchie 是的,知道,考虑到您有大约 2500 个值要在 `in` 中检查它,因此创建一个临时表将所有 2500 个项目插入到该表中,而不是在 (1,2,3,..., 2500)` 使用 `where column in (select val from temptable)`,它对 `in` 中的值数量没有限制 (2认同)
  • 我喜欢并理解您的解决方案。它对某些人有用;对我来说,我决定将列表分成块并使用 TLP 并行执行多个查询,因为使用我已有的代码似乎更简单。但我确实喜欢你的方法;赞成。 (2认同)
  • 这种方法的问题是两次 - 首先,您需要一个临时表,这在 LINQ 中很棘手。其次 - LINQ 使这 2500 次插入非常慢,这要归功于非最佳 SQL 非常慢。解决方案是使用 SqlBUlkInsert,但在代码中更加复杂并且远离 LINQ。是的,所有这些都应该由 EF 透明地处理 - 遗憾的是它不是。 (2认同)
  • 性能方面不错,但不好的是它把逻辑从 C# 层中剔除出来。如果你这样做固然很好,但这是一个笨拙的解决方法。我只是希望不需要它们。可悲的是他们是。我不喜欢的是每次有人需要 LINQ 语句的列表时都编写服务器端 tvf ;( (2认同)