2010-03-12 19 views
12

sto usando SQL Server 2005, con una base di dati sensibili caso ..LINQ to Entities: utilizzando ToLower() sui campi NTEXT

In una funzione di ricerca, ho bisogno di creare un LINQ to Entities (L2E) interrogazione con un "dove" clausola che confrontare diverse stringhe con i dati nel database con queste regole:

  1. il confronto è un "Contiene" modalità, non rigoroso confronto: facile come Contiene della stringa() il metodo è consentito in L2E
  2. Il confronto deve essere senza distinzione tra maiuscole e minuscole: utilizzo ToLower() su entrambi gli elementi per eseguire un confronto insensibile.

Tutto questo compie davvero bene, ma mi sono imbattuto nel seguente eccezione: "tipo di dati argomento ntext è valido per l'argomento 1 della funzione inferiore" su uno dei miei campi.

Sembra che il campo sia un campo NText e non riesca a eseguire ToLower() su quello.
Cosa posso fare per essere in grado di eseguire una distinzione tra maiuscole e minuscole() su quel campo NText?

risposta

26

Non utilizzare mai .ToLower() per eseguire un confronto senza distinzione tra maiuscole e minuscole. Ecco perché:

  1. È probabilmente sbagliato (le regole di confronto dei clienti potrebbero essere, ad esempio, il turco e le regole di confronto DB non).
  2. È altamente inefficiente; l'SQL Emitted è LOWER anziché = con una fascicolazione senza distinzione tra maiuscole e minuscole.

Al contrario, utilizzare o StringComparison.OrdinalIgnoreCaseStringComparison.CurrentCultureIgnoreCase:

var q = from f in Context.Foos 
     where f.Bar.Equals("hi", StringComparison.OrdinalIgnoreCase) 
     select f; 

Ma per Contains() c'è un problema: a differenza Equals, StartsWith, ecc, non ha un sovraccarico per un argomento StringComparison. Perché? Buona domanda; chiedi a Microsoft.

Questo, combinato con la limitazione di SQL Server su LOWER significa che non esiste un modo semplice per fare ciò che si desidera.

Le soluzioni possibili potrebbero includere:

  • Utilizzare un indice completo, e fare la ricerca in una procedura.
  • Utilizzare Equals o StartsWith invece, se possibile per l'attività
  • Modificare le regole di confronto predefinite della colonna?
+0

hum ... Credo che mi dici che l'uso di ToLower() è sbagliato, ma non ho altra soluzione come: - Cambiare le regole di confronto è troppo lavoro e del rischio solo per alcuni criteri di ricerca - Uguale & StartsWith vinto non è adatto alle esigenze qui Sto pensando di convertire il campo NText in NVarchar e limitare l'input dell'utente ... Le prestazioni non sono davvero importanti nel mio caso. –

+0

Sto solo cercando di dirti quali sono le opzioni, non affermando che esiste un'opzione ideale per te .... –

5

Utilizzare qui un'espressione lambda e creare un elenco di intermediari in grado di gestire la clausola inferiore.

var q = Context.Foos.ToList().Where(s => s.Bar.ToLower().Contains("hi")); 

Non molto efficiente, ma funziona.Se si dispone di predicati supplementari nella vostra clausola dove allora funziona a vostro vantaggio:

var q = Context.Foos.Where(p => p.f1 == "foo" && p.f2 == "bar"). 
      ToList().Where(s => s.Bar.ToLower().Contains("hi")); 
+1

Questo è Linq alle Entità: l'obiettivo è generare una richiesta SQL appropriata. La tua soluzione prenderà tutte le righe della tabella (o le righe filtrate con gli altri criteri) e quindi applicherà il filtro. In effetti questo non è assolutamente efficiente :). Ma ammetto che funzionerà! –

+1

Pensavo che l'obiettivo fosse un linq appropriato per le entità? In termini di efficienza ... A volte, quando il tuo cliente sta urlando per aggiustare il dannato bug e il tuo capo sta picchiettando con le dita per darti l'occhio puzzolente ... L'efficienza e le prestazioni sono molto sopravvalutate tranne nei casi in cui non lo sono. Solo perché qualcosa può essere ottimizzato non significa che debba essere. –

+2

D'accordo, l'ho appena menzionato in modo che le nuove persone che usano questa tecnica sanno quello che realmente fa (sono sempre sorpreso di vedere quante persone usano L2E senza sapere cosa succede sotto). Quindi, con tabelle grandi, potrebbe avere un impatto significativo sulle prestazioni/memoria. Nel mio caso, la performance non era importante. –

0

come si sa, questa è una situazione molto "spiati". e mi infastidisce molto.

Oggi, ho deciso di creare una vista come:

select * from tableName dove theColumn come 'chiave%%'

quindi caricare questo punto di vista in EF.

la vita è facile!

Problemi correlati