Atteindre la limite de paramètre de 2100 (SQL Server) lors de L'utilisation de Contains()
from f in CUSTOMERS
where depts.Contains(f.DEPT_ID)
select f.NAME
depts
est une liste ( IEnumerable<int>
) des noms de département
cette requête fonctionne très bien jusqu'à ce que vous passiez une grande liste (disons environ 3000 départements) .. puis j'obtiens cette erreur:
le flux du protocole D'appel de procédure à distance (RPC) pour le flux de données tabulaires entrant (TDS) est incorrect. Trop de paramètres ont été fournis dans cette demande de RPC. Le maximum est 2100.
j'ai changé ma requête en:
var dept_ids = string.Join(" ", depts.ToStringArray());
from f in CUSTOMERS
where dept_ids.IndexOf(Convert.ToString(f.DEPT_id)) != -1
select f.NAME
en utilisant IndexOf()
a corrigé l'erreur mais a fait la requête lente. Est-il un autre moyen pour résoudre ce problème? merci beaucoup.
5 réponses
ma solution (Guides - > liste des guides):
List<tstTest> tsts = new List<tstTest>();
for(int i = 0; i < Math.Ceiling((double)Guides.Count / 2000); i++)
{
tsts.AddRange(dc.tstTests.Where(x => Guides.Skip(i * 2000).Take(2000).Contains(x.tstGuid)));
}
this.DataContext = tsts;
pourquoi ne pas écrire la requête en sql et joindre votre entité?
ça fait longtemps que je n'ai pas travaillé à Linq, mais voilà:
IQuery q = Session.CreateQuery(@"
select *
from customerTable f
where f.DEPT_id in (" + string.Join(",", depts.ToStringArray()) + ")");
q.AttachEntity(CUSTOMER);
bien sûr, vous aurez besoin de protéger contre l'injection, mais cela ne devrait pas être trop difficile.
vous voudrez consulter le LINQKit project car il y a quelque part une technique pour assembler de telles déclarations pour résoudre ce problème. Je crois que l'idée est d'utiliser le PredicateBuilder pour briser la collection locale en petits morceaux, mais je n'ai pas examiné la solution en détail parce que j'ai plutôt été à la recherche d'une façon plus naturelle de gérer cela.
malheureusement, il apparaît de la réponse de Microsoft à ma suggestion pour corriger ce comportement qu'il n'y a pas de plan défini pour avoir cette adresse pour .net Framework 4.0 ou même des paquets de service ultérieurs.
https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=475984
mise à jour:
j'ai ouvert une discussion pour savoir si cela allait être fixé pour LINQ à SQL ou le ADO.NET Entity Framework sur les forums MSDN. S'il vous plaît voir ces messages pour plus d'informations sur ces sujets et de voir la solution de contournement temporaire que j'ai trouvé en utilisant XML et un UDF SQL.
vous pouvez toujours diviser votre liste de depts en plus petits ensembles avant de les passer comme paramètres à L'instruction in générée par Linq. Voir ici:
diviser un grand IEnumerable en plus petit IEnumerable d'un montant fixe de l'article