LINQ to SQL - выберите, где текст, как массив строк - PullRequest
7 голосов
/ 04 февраля 2009

У меня есть List <string> переменной count, и я хочу запросить (через LINQ) таблицу, чтобы найти любые элементы, которые содержат любую из этих строк в столбце Text.

Попробовал (не работает):

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

Запрос будет выглядеть примерно так:

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

Возможно ли это?

Ответы [ 4 ]

11 голосов
/ 06 февраля 2009

Проверьте эту статью, чтобы делать то, что вы хотите:
http://www.albahari.com/nutshell/predicatebuilder.aspx

Это работает как сон. Я по сути вырезал и вставил их код и получил его обратно (с моей собственной схемой данных, конечно):

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

Вот код, который я использовал для подтверждения концепции:

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);
    }
}
}

Я бы предложил пойти на сайт за кодом и объяснением.

(я оставляю первый ответ, потому что он хорошо работает, если вам нужен оператор IN)

6 голосов
/ 04 февраля 2009

новый для всей игры LINQ to SQL, но помогает ли этот синтаксис?

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

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

Получил от:

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

1 голос
/ 30 июня 2011

После прочтения этого поста и поиска того же решения, что и вы, я нашел решение, использующее методы .Any и .All для Linq - хороший простой и элегантный способ получения результатов сопоставления для массивов.

В этом случае я использую поисковый ввод, разделенный запятыми в качестве примера. Мне все равно, если матч не в том же случае.

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

Сначала получите некоторые данные для запроса, от Linq до SQL или где угодно

var search = db.tablename;

Использование лямбда-синтаксиса для хорошего сжатого кода, и в результате получается совпадение со строкой .Any в запросе к имени или описанию в таблице.

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

Если вы хотите получить результаты, в которых все строки совпадают в любом поле, вы можете заменить .Any на .All:

search = search.Where(
    record => 
    qry.All(q => record.Name.ToLower().Contains(q)) || 
    qry.All(q => record.Description.ToLower().Contains(q)));
0 голосов
/ 08 февраля 2014

Использование:

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

Функция поиска:

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);
}
...