Pergunta

Eu tenho uma tabela claro que eu preciso procurar com base em palavras-chave digitadas na caixa de pesquisa. Aqui está uma consulta de exemplo:

SELECT * FROM Courses WHERE 
Title LIKE '%word%' OR Title LIKE '%excel%' OR 
Contents LIKE '%word%' OR Contents LIKE '%excel%'

Como posso converter isso em LINQ onde LINQ iria gerar dinamicamente onde as declarações com base em cada palavras-chave.

Eu tentei PredicateBuilder usuário funciona bem, desde que o campo é VARCHAR. Para os campos "Texto" as aspas não são gerados, portanto, fazendo com que o compilador para dar uma mensagem de erro. Aqui está o SQL gerado pelo PredicateBuilder

SELECT [t0].[CoursesID], [t0].[Title], [t0].[Contents], [t0].[Active], 
FROM [dbo].[Courses] AS [t0]
WHERE ([t0].[Title] LIKE '%word%') OR ([t0].[Contents] LIKE %word%) OR 
([t0].Title] LIKE '%excel%') OR ([t0].[Contents] LIKE %excel%)

Observe não há uma única cotação para o campo "Conteúdo", que é um campo de texto no banco de dados.

Existe alguma maneira fácil de construir WHERE e anexá-lo com consulta? Alguém sabe como posso fazer isso sem PredicateBuilder?

Agradecemos antecipadamente.

Foi útil?

Solução

Uma vez que você está trabalhando w / LINQ eu suponho que você está trabalhando contra um certo contexto de dados LINQ to SQL? Eu não tenho um DataContext de reposição em torno de mentir para testar isso, mas isso deve dar-lhe algumas ideias.

Eu não sei se ele vai trabalhar contra o contexto de dados, porém, mas a maioria destes são coisas muito básicas (encadeamento operador OR e contém chamada de método), por isso não deve causar problemas quando a consulta se traduz em SQL.

Primeiro eu criar uma função personalizada que iria construir minha predicado:

Func<string, Func<DataItem, bool>> buildKeywordPredicate =
    keyword =>
        x => x.Title.Contains(keyword)
            || x.Contents.Contains(keyword);

Esta é uma função que leva uma única palavra-chave de cadeia e, em seguida, retornar outra função que leva um DataItem e verifica-lo contra a palavra-chave.

Basicamente, se você passar na "pilha", você vai ter um predicado:. x => x.Title.Contains("Stack") || x.Contents.Contains("Stack")

Em seguida, uma vez que existem muitas palavras-chave possíveis e você precisa cadeia com um OR operação, eu criar uma outra função auxiliar para cadeia 2 predicados juntamente com um OR

Func<Func<DataItem,bool>, Func<DataItem, bool>, Func<DataItem, bool>> buildOrPredicate =
    (pred1, pred2) =>
        x => pred1(x) || pred2(x);

Esta função leva 2 predicados e depois juntar-los com um OR operação.

Tendo essas 2 funções, então eu posso construir a minha, onde predicado como este:

foreach (var word in keywords) {            
    filter = filter == null
        ? buildKeywordPredicate(word)
        : buildOrPredicate(filter, buildKeywordPredicate(word));
}

A primeira linha dentro do loop basicamente verifica se o filtro é nula. Se é, então nós queremos um filtro de palavra-chave simples, construída por nós.

Else se o filtro não é nulo, precisamos cadeia de filtros existentes com um OR operação, de modo que passar o filtro existente e um novo filtro de palavra-chave para buildOrPredicate para fazer exatamente isso.

E, em seguida, podemos agora criar o ONDE parte da consulta:

var result = data.Where(filter);

Passando no predicado complicado que acabou de construir.

Eu não sei se isso diferente vontade de usar PredicateBuilder mas uma vez que estamos adiando tradução consulta para o motor de LINQ to SQL, não deve haver nenhum problema.

Mas, como eu disse, eu havn't testado contra um contexto de dados real, então se houver qualquer problema que você pode escrever nos comentários.

Aqui está o console app que eu construído para teste: http://pastebin.com/feb8cc1e

Espero que isso ajude!


EDIT: Para uma versão mais genérica e reutilizável que envolve utilizando adequadamente as árvores de expressão em LINQ, consulte a postagem do blog de Thomas Petricek: http://tomasp.net/articles/dynamic-linq-queries.aspx

Outras dicas

As predicate builder doesn't know the DB type of the property the Contains method is called on, I guess this might be a problem inside linq to sql. Have you tried with a normal query (not with predicate builder) and a TEXT column with Contains?

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top