Requêtes Linq Conditionnelles

on travaille sur une visionneuse de journaux. L'utilisation aura l'option de filtrer par utilisateur, gravité,etc. Dans les jours Sql j'ajouterais à la chaîne de requête, mais je veux le faire avec Linq. Comment puis-je ajouter des clauses où?

80
demandé sur Keith 2008-08-14 19:20:26

12 réponses

si vous voulez filtrer seulement si certains critères sont respectés, faites quelque chose comme ça

var logs = from log in context.Logs
           select log;

if (filterBySeverity)
    logs = logs.Where(p => p.Severity == severity);

if (filterByUser)
    logs = logs.Where(p => p.User == user);

faire ainsi permettra à votre arbre D'Expression d'être exactement ce que vous voulez. De cette façon, le SQL créé sera exactement ce dont vous avez besoin et rien de moins.

144
répondu Darren Kopp 2010-07-16 18:00:35

si vous avez besoin de filtrer la base sur une Liste / Tableau utilisez ce qui suit:

    public List<Data> GetData(List<string> Numbers, List<string> Letters)
    {
        if (Numbers == null)
            Numbers = new List<string>();

        if (Letters == null)
            Letters = new List<string>();

        var q = from d in database.table
                where (Numbers.Count == 0 || Numbers.Contains(d.Number))
                where (Letters.Count == 0 || Letters.Contains(d.Letter))
                select new Data
                {
                    Number = d.Number,
                    Letter = d.Letter,
                };
        return q.ToList();

    }
21
répondu Carlos 2011-05-09 19:36:13

j'ai fini par utiliser une réponse similaire à celle de Daren, mais avec une interface IQueryable:

IQueryable<Log> matches = m_Locator.Logs;

// Users filter
if (usersFilter)
    matches = matches.Where(l => l.UserName == comboBoxUsers.Text);

 // Severity filter
 if (severityFilter)
     matches = matches.Where(l => l.Severity == comboBoxSeverity.Text);

 Logs = (from log in matches
         orderby log.EventTime descending
         select log).ToList();

qui construit la requête avant de frapper la base de données. La commande ne fonctionnera pas jusqu'à ce que .ToList() à la fin.

19
répondu sgwill 2008-08-21 13:50:32

quand il s'agit de LINQ conditionnel, je suis très friand des filtres et des pipes.

http://blog.wekeroad.com/mvc-storefront/mvcstore-part-3 /

fondamentalement, vous créez une méthode d'extension pour chaque boîtier de filtre qui prend L'IQueryable et un paramètre.

public static IQueryable<Type> HasID(this IQueryable<Type> query, long? id)
{
    return id.HasValue ? query.Where(o => i.ID.Equals(id.Value)) : query;
}
13
répondu Lars Mæhlum 2008-08-14 22:03:19

une autre option serait d'utiliser quelque chose comme le Prédicatebuilder discuté ici . Il vous permet d'écrire le code comme suit:

var newKids  = Product.ContainsInDescription ("BlackBerry", "iPhone");

var classics = Product.ContainsInDescription ("Nokia", "Ericsson")
                  .And (Product.IsSelling());

var query = from p in Data.Products.Where (newKids.Or (classics))
            select p;

notez que je n'ai que ça pour fonctionner avec Linq 2 SQL. Entitefram Framework ne met pas en œuvre L'Expression.Invoquer, ce qui est nécessaire pour que cette méthode fonctionne. J'ai une question concernant cette question ici .

3
répondu Brad Leach 2017-05-23 12:16:56

:

bool lastNameSearch = true/false; // depending if they want to search by last name,

ayant ceci dans l'énoncé where :

where (lastNameSearch && name.LastNameSearch == "smith")

signifie que lorsque la requête finale est créée, si lastNameSearch est false la requête omettra complètement N'importe quel SQL pour la recherche de nom de famille.

3
répondu Craig Livingston 2011-12-26 19:42:57

ce n'est pas la chose la plus jolie mais vous pouvez utiliser une expression lambda et passer vos conditions facultativement. Dans TSQL je fais beaucoup de ce qui suit pour rendre les paramètres optionnels:

où Field = @FieldVar ou @FieldVar est nul

vous pouvez dupliquer le même style avec la lambda suivante (un exemple de vérification de l'authentification):

MyDataContext db = new MyDataContext();

nul RunQuery(string param1, chaîne param2, int? param3) {

Func checkUser d'utilisateur = = >

((param1.Longueur > 0)? utilisateur.Param1 = = param1 : 1 == 1) &&

((param2.Longueur > 0)? utilisateur.Param2 = = param2 : 1 == 1) &&

((param3 != null)? utilisateur.Param3 = = param3 : 1 = = 1);

User foundUser = db.Utilisateur.SingleOrDefault (checkUser);

}

1
répondu t3rse 2008-08-14 15:53:50

j'ai eu récemment une exigence semblable et j'ai finalement trouvé cela dans le MSDN. Csharp Samples for Visual Studio 2008

les classes incluses dans L'échantillon DynamicQuery du téléchargement vous permettent de créer des requêtes dynamiques à l'exécution dans le format suivant:

var query =
db.Customers.
Where("City = @0 and Orders.Count >= @1", "London", 10).
OrderBy("CompanyName").
Select("new(CompanyName as Name, Phone)");

en utilisant ceci vous pouvez construire une chaîne de requête dynamiquement à l'exécution et la passer dans la méthode où ():

string dynamicQueryString = "City = \"London\" and Order.Count >= 10"; 
var q = from c in db.Customers.Where(queryString, null)
        orderby c.CompanyName
        select c;
1
répondu Andy Rose 2008-08-18 13:12:06

j'ai résolu cela avec une méthode d'extension pour permettre à LINQ d'être conditionnellement activé au milieu d'une expression fluide. Cela supprime la nécessité de casser l'expression avec les énoncés if .

"151930920 l'extension de la méthode:

public static IQueryable<TSource> If<TSource>(
        this IQueryable<TSource> source,
        bool condition,
        Func<IQueryable<TSource>, IQueryable<TSource>> branch)
    {
        return condition ? source : branch(source);
    }

cela vous permet de faire ceci:

return context.Logs
     .If(filterBySeverity, q => q.Where(p => p.Severity == severity))
     .If(filterByUser, q => q.Where(p => p.User == user))
     .ToList();
1
répondu Ryan 2018-07-11 06:50:53

il suffit d'utiliser C#' & & de l'opérateur:

var items = dc.Users.Where(l => l.Date == DateTime.Today && l.Severity == "Critical")

Edit: Ah, faut lire plus attentivement. Vous voulais savoir comment conditionnellement ajouter des clauses supplémentaires. Dans ce cas, je n'ai aucune idée. :) Ce que je ferais probablement est juste préparer plusieurs requêtes, et exécuter la bonne, en fonction de ce que j'ai fini par avoir besoin.

0
répondu TheSmurf 2008-08-14 15:26:12

vous pouvez utiliser une méthode externe:

var results =
    from rec in GetSomeRecs()
    where ConditionalCheck(rec)
    select rec;

...

bool ConditionalCheck( typeofRec input ) {
    ...
}

cela fonctionnerait, mais ne peut pas être décomposé en arbres d'expression, ce qui signifie que Linq à SQL exécuterait le code de contrôle contre chaque enregistrement.

alternativement:

var results =
    from rec in GetSomeRecs()
    where 
        (!filterBySeverity || rec.Severity == severity) &&
        (!filterByUser|| rec.User == user)
    select rec;

qui pourrait fonctionner dans des arbres d'expression, ce qui signifie Linq à SQL serait optimisé.

0
répondu Keith 2008-08-14 15:34:29

Eh bien, ce que je pensais était que vous pourriez mettre les conditions de filtre dans une liste générique de prédicats:

    var list = new List<string> { "me", "you", "meyou", "mow" };

    var predicates = new List<Predicate<string>>();

    predicates.Add(i => i.Contains("me"));
    predicates.Add(i => i.EndsWith("w"));

    var results = new List<string>();

    foreach (var p in predicates)
        results.AddRange(from i in list where p.Invoke(i) select i);               

qui donne une liste contenant" me"," meyou", et"mow".

vous pourriez optimiser cela en faisant la foreach avec les prédicats dans une fonction totalement différente qui ORs tous les prédicats.

0
répondu Jon Limjap 2008-08-14 15:39:33