2009-08-07 10 views
0

J'ai une requête LINQ qui recherche une chaîne (en utilisant une regex) dans plusieurs champs. Je veux trier les résultats en fonction du champ dans lequel le texte a été trouvé.Trier par critères de recherche C# LINQ

Actuellement, j'ai ceci:

var results = from i in passwordData.Tables["PasswordValue"].AsEnumerable() 
      where r.IsMatch(i.Field<String>("Key").Replace(" ","")) || 
      r.IsMatch(i.Field<String>("Username").Replace(" ","")) || 
      r.IsMatch(i.Field<String>("Other").Replace(" ","")) 
      orderby i.Field<String>("Key"), 
      i.Field<String>("Other"), 
      i.Field<String>("Username") 
      select i; 

Je veux correspondances trouvées dans la première clé, puis les matchs trouvés dans d'autres, et les matchs puis trouvé Nom d'utilisateur. Si possible, les correspondances qui correspondent à la fois à la clé et à l'autre doivent être effectuées avant les correspondances qui correspondent uniquement à la clé.

Le code que j'ai actuellement sortes basé sur la première clé, donc si une correspondance est trouvée sur l'autre, mais commence avec une clé A, il sera un tri avant correspondance trouvée clé où commence la clé avec un Z.

Merci d'avance, ce n'est pas une question difficile, je pense, mais je ne peux pas comprendre comment faire cela comme je suis nouveau à LINQ.

Répondre

7

En utilisant le mot-clé let pour capturer des valeurs intermédiaires, vous pouvez trier facilement par le fait que il y avait un match avant de trier les valeurs reconnues:

var results = from i in passwordData.Tables["PasswordValue"].AsEnumerable() 
       let fields = new { 
        Key = i.Field<String>("Key"), 
        Username = i.Field<String>("Username"), 
        Other = i.Field<String>("Other") } 
       let matches = new { 
        Key = r.IsMatch(fields.Key.Replace(" ","")), 
        Username = r.IsMatch(fields.Username.Replace(" ","")), 
        Other = r.IsMatch(fields.Other.Replace(" ","")) } 
       where matches.Key || matches.Username || matches.Other 
       orderby matches.Key descending, fields.Key, 
       matches.Username descending, fields.Username, 
       matches.Other descending, fields.Other 
       select i; 
+0

Merci beaucoup, cela a fonctionné! – Ruud

0

Votre seule solution est de créer 2 méthodes, une pour la recherche de clé et une pour la recherche d'autres. Ensuite, basé sur le champ qui a été frappé sur la recherche, vous exécutez l'ordre par. Bien que cela puisse être un codage supplémentaire, c'est la seule façon de le faire sans créer vos propres arbres d'expression, ce qui est beaucoup plus difficile.

0

est ici un simple, mais sous-optimale performant, façon de le faire:

static IEnumerable<DataRow> DoSearch(DataTable table, RegEx r, string fieldName) { 
    return table.AsEnumerble() 
       .Where(row => r.IsMatch(row.Field<string>(fieldName).Replace(" ", "")) 
       .OrderBy(row => row.Field<string>(fieldName)); 

} 

var table = passwordData.Tables["PasswordValue"]; 
var results = DoSearch(table, r, "Key") 
    .Union(DoSearch(table, r, "Username") 
    .Union(DoSearch(table, r, "Other"); 

La méthode Union va filtrer les doublons dans le cas où une ligne correspond à plus d'un champ.