Domanda

Ho la seguente query LINQ:

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

parole chiave è un campo delimitato da virgole.

Ogni volta che funzionare questa domanda io ottenere il seguente errore:

"LINQ to Entities non riconosce il metodo 'booleana contiene [String] (System.Collections.Generic.IEnumerable`1 [System.String], System.String)' metodo, e questo metodo non può essere tradotto in un'espressione negozio. "

Qual è l'alternativa per quello che sto cercando di fare?

È stato utile?

Soluzione

In risposta alle vostre considerazioni sulle prestazioni su un grande insieme di dati:

Si sta per essere facendo corrispondenza non indicizzato stringa di caratteri jolly sul client, quindi sì, ci sarà perdita di prestazioni.

C'è un motivo per cui si dispone di più parole chiave in un campo di una tabella? Si potrebbe normalizzare che fuori, di avere un tavolo ActivityKeywords in cui per ogni attività si dispone di un numero di record chiave.

Attività (activity_id, ... / * rimuovere le parole chiave campo * /) ---> ActivityKeywords (activity_id, keyword_id) ---> Parole (keyword_id, valore)

Check out non prima forma normale: http://en.wikipedia.org/wiki/Database_normalization

EDIT: Inoltre, anche se si dovesse rimanere con l'una colonna, c'è un modo di fare tutto serverside (se si dispone di una sintassi rigorosa: 'keyword1, keyword2, ..., keywordN'):

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

Altri suggerimenti

Il problema è che LINQ-to-entités deve tradurre tutto ciò che si dà in SQL da inviare al database.

Se questo è davvero quello che devi fare, dovrete per forza LINQ to Entities a tirare indietro tutti i dati e LINQ to Objects per valutare la condizione.

Esempio:

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

Attenzione però, che questo si tirerà indietro tutti gli oggetti dalla tabella Attività. Un'alternativa potrebbe essere quella di lasciare che il DB fare un po 'di un filtro iniziale e filtrare verso il basso il resto del modo in seguito:

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

che vi permetterà di LINQ to Entities fare il filtro capisce (string.Contains diventa una query simili) che filtri giù alcuni dei dati, quindi applicare il vero e proprio filtro che si desidera tramite LINQ to Objects, una volta che avete gli oggetti posteriori. I ToList () forze di chiamata LINQ to Entities per eseguire la query e costruire gli oggetti, permettendo LINQ to Objects per essere il motore che fa la seconda parte della query.

La mia ipotesi è il modo in cui si sta chiamando Spalato. Si dovrebbe prendere un array. Forse c'è un altro Spalato in Linq è trovare e dando un errore insolito:

Questo funziona per LINQ to Objects:

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

Uscite il seguente:

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

In realtà, a pensarci, non è necessario la divisione a tutti? a.Contains("foo") può essere sufficiente per voi (a meno che non si vuole colpire foobar).

Si consiglia di un'occhiata a questa domanda sulla L2E e .Contains per una soluzione che dovrebbe essere più efficiente di indovinare un superset prima di filtrare lato client.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top