2011-08-01 3 views
1

Je réécris une requête créée en réponse à l'entrée de l'utilisateur dans des champs de texte afin d'offrir une protection contre les attaques par injection SQL.Création de Linq dynamique

SELECT DISTINCT (FileNameID) FROM SurNames WHERE Surname IN 
('Jones','Smith','Armitage') 
AND FileNameID IN (SELECT DISTINCT (FileNameID) FROM FirstNames WHERE FirstName 
IN ('John','William')) 

Il peut y avoir jusqu'à 3 autres tables impliquées dans ce processus. Les listes de paramètres peuvent contenir jusqu'à 50-100 entrées. La création d'une requête paramétrée est donc fastidieuse et fastidieuse.

J'essaie de créer une requête Linq qui devrait prendre en charge le paramétrage et offrir la protection dont j'ai besoin.

Cela me donne ce que je dois

var surnameValues = new[] { "Jones","Smith","Armitage" }; 
    var firstnameValues = new[] { "John","William" }; 

    var result = (from sn in db.Surnames 
       from fn in db.FirstNames 
       where surnameValues.Contains(sn.Surname) && 
       firstnameValues.Contains(fn.FirstName) 
       select fn.FileNameID).Distinct().ToArray(); 

J'ai besoin maintenant un moyen de créer de façon dynamique en fonction de ce que l'utilisateur a sélectionné/valeurs entrées dans les zones de saisie de texte ou nom firstname?

Tous les pointeurs seront reçus avec reconnaissance

Merci Roger

Répondre

1

vous pouvez combiner toute la logique dans la requête;

var surnameValues = new[] { "Jones","Smith","Armitage" }; 
var firstnameValues = null; 

// Set these two variables to handle null values and use an empty array instead 
var surnameCheck= surnameValues ?? new string[0]; 
var firstnameCheck= firstnameValus ?? new string[0]; 

var result = (from sn in db.Surnames 
      from fn in db.FirstNames 
      where 
      (!surnameCheck.Any() || surnameCheck.Contains(sn.Surname)) && 
      (!firstnameCheck.Any() || firstnameCheck.Contains(fn.FirstName)) 
      select fn.FileNameID).Distinct().ToArray(); 

Votre requête ne semble pas avoir une condition de jointure betwwen la table des noms et la table prénoms?

Vous pouvez dynamiquement construire la requête (comme vous semblez le faire, je croise rejoins je l'ai utilisé SelectMany)

var query=db.Surnames.SelectMany(sn=>db.FirstNames.Select (fn => new {fn=fn,sn=sn})); 
if (surnameValues!=null && surnameValues.Any()) query=query.Where(x=>surnameValues.Contains(x.sn.Surname)); 
if (firstnameValues !=null && firstnameValues.Any()) query=query.Where(x=>firstnameValues.Contains(x.fn.FirstName)); 
var result=query.Select(x=>x.fn.FileNameID).Distinct(); 
+0

Merci Bob, qui est très utile. Je suis parti en bas de cette route mais je me suis battu avec car vous avez souligné que certaines des tables ne sont pas jointes et où ils sont nécessaires une jointure complète que je ne pouvais pas trouver facilement comment faire dans Linq. Le principal problème que j'avais était avec la déclaration des tables au cas où il n'y avait pas de clause additionnelle where. c'est-à-dire que l'utilisateur ne sélectionne que le nom de famille, donc aucun modificateur de prénom n'a été ajouté à la requête where. Votre exemple et l'utilisation du SelectMany ont été une véritable révélation - merci beaucoup. – RogerDodge

+0

Une chose qui pourrait vous aider est que si vous regardez [LinqPad] (http://www.linqpad.net) il peut vous donner la syntaxe lambda pour vos requêtes linq et vous donnera le même selectmany pour la jointure croisée . Peut économiser beaucoup de temps –

+0

J'ai regardé brièvement LinqPad - ai-je besoin de la version payante pour vraiment benfit? ont frappé un autre problème à faire avec Nulls si le tableau n'a pas été rempli parce que l'utilisation ne l'a pas choisi! où && génère une exception (surnameValues.Any() || surnameValues.Contains (sn.Surname)!) (FirstnameValues.Any() || firstnameValues.Contains (fn.FirstName)!) - I avoir essayé d'ajouter firstnameValues ​​== null || dans la clause where, mais ça ne marche pas ?? – RogerDodge