2009-02-04 14 views
7

Ho un elenco <string> di conteggio di variabili e voglio interrogare (tramite LINQ) una tabella per trovare tutti gli elementi che contengono una qualsiasi di quelle stringhe nella colonna Testo.LINQ to SQL: selezionare il tipo di stringa di stringhe

provato questo (non funziona):

items = from dbt in database.Items 
     where (stringList.FindAll(s => dbt.Text.Contains(s)).Count > 0) 
     select dbt; 

Query sarebbe qualcosa di simile:

select * from items where text like '%string1%' or text like '%string2%' 

è possibile?

risposta

11

controllare questo articolo a fare ciò che si vuole:
http://www.albahari.com/nutshell/predicatebuilder.aspx

Questo funziona come un sogno. I sostanzialmente tagliato e incollato il loro codice e ottenuto questo posteriore (con la mia tecnica d'schema ovviamente):

SELECT [t0].[Id], [t0].[DateCreated], [t0].[Name] ... 
FROM [dbo].[Companies] AS [t0] 
WHERE ([t0].[Name] LIKE @p0) OR ([t0].[Name] LIKE @p1) 

Ecco il codice mi sono imbattuto per la prova di concetto:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Linq.Expressions; 

namespace PredicateTest 
{ 
class Program 
{ 
    static void Main(string[] args) 
    { 
     DataClasses1DataContext dataContext = new DataClasses1DataContext(); 

     Program p = new Program(); 
     Program.SearchCompanies("test", "test2"); 
     var pr = from pi in dataContext.Companies.Where(Program.SearchCompanies("test", "test2")) select pi; 
    } 

    DataClasses1DataContext dataContext = new DataClasses1DataContext(); 

    public static Expression<Func<Company, bool>> SearchCompanies(
                params string[] keywords) 
    { 
     var predicate = PredicateBuilder.False<Company>(); 
     foreach (string keyword in keywords) 
     { 
      string temp = keyword; 
      predicate = predicate.Or(p => p.Name.Contains(temp)); 
     } 
     return predicate; 
    } 

} 

public static class PredicateBuilder 
{ 
    public static Expression<Func<T, bool>> True<T>() { return f => true; } 
    public static Expression<Func<T, bool>> False<T>() { return f => false; } 

    public static Expression<Func<T, bool>> Or<T>(this Expression<Func<T, bool>> expr1, 
                 Expression<Func<T, bool>> expr2) 
    { 
     var invokedExpr = Expression.Invoke(expr2, expr1.Parameters.Cast<Expression>()); 
     return Expression.Lambda<Func<T, bool>> 
       (Expression.OrElse(expr1.Body, invokedExpr), expr1.Parameters); 
    } 

    public static Expression<Func<T, bool>> And<T>(this Expression<Func<T, bool>> expr1, 
                 Expression<Func<T, bool>> expr2) 
    { 
     var invokedExpr = Expression.Invoke(expr2, expr1.Parameters.Cast<Expression>()); 
     return Expression.Lambda<Func<T, bool>> 
       (Expression.AndAlso(expr1.Body, invokedExpr), expr1.Parameters); 
    } 
} 
} 

I' d suggerisco di andare sul sito per il codice e la spiegazione.

(lascio la prima risposta perché funziona bene se avete bisogno di una dichiarazione IN)

6

tipo di nuovo all'intero gioco LINQ to SQL, ma questa sintassi aiuta?

string[] items = new string[] { "a", "b", "c", "d" }; 

var items = from i in db.Items 
      where items.Contains(p.text) 
      select i; 

preso da:

http://blog.wekeroad.com/2008/02/27/creating-in-queries-with-linq-to-sql/

+0

Che certo dovrebbe funzionare –

+3

Grazie per l'idea Matthew, ma che genera il seguente SQL:.. SELECT [t0] [Testo] FROM [dbo] [Tabella] AS [T0] WHERE [T0 ]. [Testo] IN (@ p0) Cerca la colonna di testo in ogni elemento dell'array piuttosto che cercare ogni elemento dell'array nella colonna di testo. – bjallen

1

Dopo aver letto questo post, cercando la stessa soluzione, come voi, ho trovato una soluzione utilizzando i metodi .Any e .All per Linq è un modo semplice ed elegante per ottenere risultati corrispondenti per gli array.

In questo caso sto utilizzando un input di ricerca, separato da virgole come esempio. Non mi interessa se la partita non è nello stesso caso.

var qry = Query.Split(',').Select(c => c.Trim().ToLower()); 

prima ottenere alcuni dati per interrogare, da LINQ to SQL o dovunque

var search = db.tablename; 

Utilizzando la sintassi lambda per bel codice stretto, e si traducono in partite per .Any stringa nella query a uno il nome o descrizione nella tabella.

search = search.Where(
    record => 
    qry.Any(q => record.Name.ToLower().Contains(q)) || 
    qry.Any(q => record.Description.ToLower().Contains(q))); 

Se si desidera che solo i risultati in cui tutte le stringhe sono abbinati all'interno di ogni campo è possibile sostituire .Any con .All:

search = search.Where(
    record => 
    qry.All(q => record.Name.ToLower().Contains(q)) || 
    qry.All(q => record.Description.ToLower().Contains(q))); 
0

Usando:

string searh = "test1 test2,test3";  
data.Persons.Search(p => p.Name, search); 

funzione di ricerca è:

public static IQueryable<T> Search<T>(this IQueryable<T> source, Expression<Func<T, string>> selector, string s) 
{ 
    if (string.IsNullOrEmpty(s)) 
     return source; 

    string[] str = s.Split(new char[] { ' ', ',' }, StringSplitOptions.RemoveEmptyEntries); 

    MethodInfo methodContains = typeof(string).GetMethod("Contains", new[] { typeof(string) }); 

    Expression strExpression; 
    Expression expressionContains; 
    Expression resultExpression = Expression.Empty(); 

    for (int i = 0; i < str.Length; i++) 
    { 
     strExpression = Expression.Constant(str[i].Trim(), typeof(string)); 
     expressionContains = Expression.Call(selector.Body, methodContains, strExpression); 

     if (i == 0) 
      resultExpression = expressionContains; 
     else 
      resultExpression = Expression.OrElse(resultExpression, expressionContains); 
    } 

    Expression<Func<T, bool>> lambdaExpr = Expression.Lambda<Func<T, bool>>(resultExpression, new ParameterExpression[] { selector.Parameters[0] }); 

    return source.Where(lambdaExpr); 
}