Linq.包含大集合会导致TDS错误 [英] Linq .Contains with large set causes TDS error

查看:90
本文介绍了Linq.包含大集合会导致TDS错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我稍微简化了一下,因为我正在寻找通用答案.假设我有这样的表格设置:

I've oversimplified this a bit, because I'm looking for a general-purpose answer. Let's say I've got a table setup like this:

Parent
recno    int (unique, pk)
date     datetime
stuff    varchar(50)

Child
parentrecno (int, fk)   --- PK
sequence    (int)       --- PK
data     varchar(50)

在我的C#程序中,我经历了很多麻烦,以查找我感兴趣的父记录并将其填充到列表中. Parent是一个非常大的表,我宁愿不要查询过多的表.所以我松开了钥匙:

And in my C# program I've gone through a lot of hassle to find the Parent records that I'm interested in and stuff them into a list. Parent is a really large table, and I'd rather not query it more than necessary. So I squirrel away the keys:

List<int> recs = (from d in Parent where [.....] select d.recno).ToList();

稍后我可以说,在Linq中,找到相关父母的所有孩子记录:

Later on in Linq I can say, find all of the child records for the associated parents:

var kids = from k in database.Childs
      where recs.Contains(k.parentrecno)
      select new { k };

这很好,直到recs包含2100多个条目.然后,我得到一个TDS RPC错误(参数太多).

This is all great until recs contains more than 2100 entries. Then I get a TDS RPC error (too many parameters).

我看到的方式是:

  • 使用SQL直接完成整个过程(不是真的想通过DataReader来解决麻烦,等等).限定记录涉及一个外部系统,所以我也不知道这是否完全可能.另外,我将生成该列表两次-一次,当我需要在.Contains()中使用它时,再一次,将其用于其他目的.

  • Do the whole thing in straight up SQL (didn't really want to do go through the hassle with a DataReader, etc...). There was an external system involved in qualifying the records, so I don't know if that's entirely possible either. Plus, I'd be generating that list twice -- once when I need to use it in .Contains(), and again for other purposes.

向上分解列表(记录),然后分块读取Child.

Break the list (recs) up, and then read Child in chunks.

如果我将其拆成小块,那么我漂亮的Linq一点也不用:

If I break it up in chunks, then my pretty Linq a little farther down won't work at all:

var kids2 = (from kid in paydb.Childs
         where
             recs.Contains(kid.parentrecno)
         group pay by kid.parentrecno into kgroup
         select new { ParentRecNo = kgroup.Key, KidRecords = kgroup })
              .ToDictionary(kx => kx.ParentRecNo);

因为List记录将包含需要分组在一起的内容,但对于Linq查询却必须分开.

Because the List recs will contain things that needed to be grouped together, but necessarily split apart for the Linq query.

推荐答案

我们使用SQL函数,该函数以varchar(max)分隔的值列表作为参数并返回表变量. linq看起来像这样:

We use a SQL function taking a varchar(max) delimited list of values as an argument and returning a table variable. The linq looks like this:

from a in Context.SomeTable    
join nl in Context.ParseDelimited(nodeIdList) on a.NodeId.ToString() equals nl.FieldValue

其中nodeIdList是一个字符串变量,其中包含上一个查询的ID列表.丑陋,但确实能达到2100参数的限制.

where nodeIdList is a string variable containing the list of ids from a previous query. Ugly, but it does get around the 2100 parameter limit.

create function dbo.ParseDelimited(@delimitedList NVARCHAR(MAX)) returns @tblSample table(counter int, fieldValue NVARCHAR(100)) 
WITH SCHEMABINDING
as
begin
  declare @counter    NVARCHAR(  4)
  declare @fieldValue NVARCHAR(100)

  declare @tmpTable table(counter int primary key, fieldValue NVARCHAR(100))

  set @counter = 1

  while charindex(',', @delimitedList) > 0
  begin
    set @fieldValue = ltrim(rtrim(substring(@delimitedList, 1, charIndex(',', @delimitedList)-1)))

    insert into @tmpTable select @counter, @fieldValue

    set @delimitedList = ltrim(rtrim(substring(@delimitedList, (charindex(',', @delimitedList) + 1), len(@delimitedList))))

    set @counter = @counter + 1
  end

  if ltrim(rtrim(@delimitedList)) != ''
  begin
    insert into @tmpTable select @counter, @delimitedList
  end

  insert into @tblSample select counter, fieldValue from @tmpTable

  return
end

这篇关于Linq.包含大集合会导致TDS错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆