Pergunta

Eu tenho a seguinte consulta LINQ:

var aKeyword = "ACT";
var results = from a in db.Activities
              where a.Keywords.Split(',').Contains(aKeyword) == true
              select a;

Palavras -chave é um campo delimitado por vírgula.

Toda vez que executo esta consulta, recebo o seguinte erro:

"O LINQ para entidades não reconhece o método 'Boolean contém [String] (System.Collection.Genic.ienumerable`1 [System.String], System.String)', e esse método não pode ser traduzido para uma expressão de loja."

Qual é a alternativa para o que estou tentando fazer?

Foi útil?

Solução

Em resposta às suas considerações de desempenho em um grande conjunto de dados:

Você fará correspondência de cordas curinga não indexada no cliente, então sim, haverá perda de desempenho.

Existe uma razão pela qual você tem várias palavras -chave em um campo de tabela? Você pode normalizar isso, para ter uma tabela ActivityKeywords onde, para cada atividade, você tem vários registros de palavras -chave.

Atividades (Atividades_id, ... / * Remova palavras-chave Campo * /) ---> AtividadeKeyWords (Activity_Id, Keyword_id) ---> Palavras-chave (Keyword_id, Valor)

Confira o primeiro formulário normal: http://en.wikipedia.org/wiki/database_normalization

EDIT: Também mesmo se você se mantiver com a coluna, existe uma maneira de fazer tudo o que é o servidor (se você tiver uma sintaxe estrita: 'Palavra -chave1, palavra -chave2, ..., palavra -chave'):

var aKeyword = "ACT";
var results = (from a in db.Activities
              where a.Keywords.Contains("," + aKeyword) || a.Keywords.Contains(aKeyword + ",")
              select a;

Outras dicas

Seu problema é que o Linq-para-Entites deve traduzir tudo o que você fornece no SQL para enviar para o banco de dados.

Se é realmente o que você precisa fazer, você terá que forçar o LINQ-para-endidades a recuperar todos os dados e os objetos LINQ para avaliar a condição.

Ex:

var aKeyword = "ACT";
var results = from a in db.Activities.ToList()
              where a.Keywords.Split(',').Contains(aKeyword) == true
              select a;

Esteja ciente, porém, que isso recuará todos os objetos da tabela de atividades. Uma alternativa pode ser deixar o banco de dados fazer um filtro inicial e filtrar o resto do caminho depois:

var aKeyword = "ACT";
var results = (from a in db.Activities
              where a.Keywords.Contains(aKeyword)
              select a).ToList().Where(a => a.KeyWords.Split(',').Contains(aKeyword));

Isso permitirá que o Linq-to-Entities faça o filtro que ele entende (String.Contains se torna uma consulta semelhante) que filtrará alguns dos dados e aplicará o filtro real que você deseja via Linq-to-Objects depois de ter os objetos de volta . O Tolist () chama o Linq-to-Oentities a executar a consulta e construir os objetos, permitindo que o Linq-to-Objects seja o mecanismo que faz a segunda parte da consulta.

Meu palpite é a maneira como você está chamando a divisão. Deve levar uma matriz. Talvez haja outra divisão no LINQ, está encontrando e oferecendo um erro incomum:

Isso funciona para o LINQ aos objetos:

 var dataStore = new List<string>
                    {
                        "foo,bar,zoo",
                        "yelp,foo",
                        "fred",
                        ""
                    };
 var results = from a in dataStore
               where a.Split(new[] {','}).Contains("foo")
               select a;

 foreach (var result in results)
 {
     Console.WriteLine("Match: {0}", result);
 }

Produz o seguinte:

Match: foo,bar,zoo
Match: yelp,foo

Na verdade, pensando nisso, você precisa da divisão? a.Contains("foo") pode ser suficiente para você (a menos que você não queira bater foobar).

Você pode querer Veja esta pergunta sobre L2E e. Para uma solução que deve ser mais eficiente do que adivinhar um superconjunto antes de filtrar o lado do cliente.

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