web-dev-qa-db-fra.com

LINQ to SQL Critères facultatifs de clause Where

Je travaille avec une requête LINQ to SQL et j'ai rencontré un problème où j'ai 4 champs facultatifs pour filtrer le résultat des données. Par facultatif, je veux dire a le choix d'entrer une valeur ou non. Plus précisément, quelques zones de texte qui pourraient avoir une valeur ou avoir une chaîne vide et quelques listes déroulantes qui auraient pu avoir une valeur sélectionnée ou peut-être pas ...

Par exemple:

    using (TagsModelDataContext db = new TagsModelDataContext())
     {
        var query = from tags in db.TagsHeaders
                    where tags.CST.Equals(this.SelectedCust.CustCode.ToUpper()) 
                    && Utility.GetDate(DateTime.Parse(this.txtOrderDateFrom.Text)) <= tags.ORDDTE
                    && Utility.GetDate(DateTime.Parse(this.txtOrderDateTo.Text)) >= tags.ORDDTE
                    select tags;
        this.Results = query.ToADOTable(rec => new object[] { query });
    }

Maintenant, je dois ajouter les champs/filtres suivants, mais uniquement s'ils sont fournis par l'utilisateur.

  1. Numéro de produit - Provient d'une autre table qui peut être jointe à TagsHeaders.
  2. Numéro de bon de commande - un champ dans la table TagsHeaders.
  3. Numéro de commande - Similaire au PO #, juste une colonne différente.
  4. Statut du produit - Si l'utilisateur l'a sélectionné dans une liste déroulante, vous devez appliquer la valeur sélectionnée ici.

La requête que j'ai déjà fonctionne très bien, mais pour terminer la fonction, vous devez pouvoir ajouter ces 4 autres éléments dans la clause where, je ne sais pas comment!

70
RSolberg

Vous pouvez coder votre requête d'origine:

var query = from tags in db.TagsHeaders
                where tags.CST.Equals(this.SelectedCust.CustCode.ToUpper()) 
                && Utility.GetDate(DateTime.Parse(this.txtOrderDateFrom.Text)) <= tags.ORDDTE
                && Utility.GetDate(DateTime.Parse(this.txtOrderDateTo.Text)) >= tags.ORDDTE
                select tags;

Et puis, en fonction d'une condition, ajoutez des contraintes Where supplémentaires.

if(condition)
    query = query.Where(i => i.PONumber == "ABC"); 

Je ne sais pas comment coder cela avec la syntaxe de requête, mais id fonctionne avec un lambda. Fonctionne également avec la syntaxe de requête pour la requête initiale et un lambda pour le filtre secondaire.

Vous pouvez également inclure une méthode d'extension (ci-dessous) que j'ai codée il y a quelque temps pour inclure des instructions conditionnelles where. (Ne fonctionne pas bien avec la syntaxe de requête):

        var query = db.TagsHeaders
            .Where(tags => tags.CST.Equals(this.SelectedCust.CustCode.ToUpper()))
            .Where(tags => Utility.GetDate(DateTime.Parse(this.txtOrderDateFrom.Text)) <= tags.ORDDTE)
            .Where(tags => Utility.GetDate(DateTime.Parse(this.txtOrderDateTo.Text)) >= tags.ORDDTE)
            .WhereIf(condition1, tags => tags.PONumber == "ABC")
            .WhereIf(condition2, tags => tags.XYZ > 123);

La méthode d'extension:

public static IQueryable<TSource> WhereIf<TSource>(
    this IQueryable<TSource> source, bool condition,
    Expression<Func<TSource, bool>> predicate)
{
    if (condition)
        return source.Where(predicate);
    else
        return source;
}

Voici la même méthode d'extension pour IEnumerables:

public static IEnumerable<TSource> WhereIf<TSource>(
    this IEnumerable<TSource> source, bool condition,
    Func<TSource, bool> predicate)
{
    if (condition)
        return source.Where(predicate);
    else
        return source;
}
120
andleer

Il suffit d'utiliser une vérification conditionnelle de l'existence du paramètre. Par exemple:

where (string.IsNullOrEmpty(ProductNumber) || ProductNumber == tags.productNumber)

De cette façon, si le numéro de produit n'est pas entré, cette expression retournera vrai dans tous les cas, mais s'il est entré, il ne retournera vrai que lors de la correspondance.

31
CodeRedick

Vous avez la possibilité de OR avec ||.

Consultez ce fil, car il pourrait vous donner quelques bons pointeurs: équivalent C # LINQ d'une requête SQL quelque peu complexe

0
Gregory A Beamer