Gå til innhold

Bruk av collection.contains() i et LINQ uttrykk tar laaaaaaaang tid


Anbefalte innlegg

Folkens...

Jeg prøver å bygge et LINQ uttrykk Runtime på bakgrunn av en del propmpts jeg har i en form. Uttrykket brukes for å søke i en tabell over ord/uttrykk som er brukt i dokumenter.  Dette fungerer veldig bra fordi jeg bruker IQUERYABLE. 

Noe slik:

 

var records = from record in dbContext.WordTable

                      Select record;

 

 

Så kommer det en del greier som påvirker ting, som ikke er av interresse, men følgende gir hodepine:

records = records.Where(r => wordsToSearch.Contains(r.Word));

 

WordsToSearch er en List<String> som inneholder alle ordene som skal søkes på. 

 

Dette fungerer, men tar fryktelig lang tid.  Så analyserer jeg det faktiske SELECT statementet og ser følgende (herunder er ordet 'prosesskriv' valgt i GUI:

.....

   WHERE ([Extent1].[Word] IN (N'prosesskriv'))

.....

Legg merke til N som er bygget inn i uttrykket.  Dette betyr jo National character.  Tabellen har 50 milioner records og søket resulterer i 5000 treff og tar over 5 minutter.

Hvis jeg manuellt tester det genererte uttrykket tar det akkurat like lang tid, men fjerner jeg N fra IN uttrykket så får jeg samme resultat, men søket tar 2 sekunder.

 

Jeg tenker jo at N sikkert er viktig i mange situasjoner, men i denne sammenhengen er det kun brukt i Norge og jeg går ut ifra at ingen tenker på å skrive en masse kryptiske tegn når de søker. 

 

Spørsmålet er derfor:  Hvordan får jeg vekk den N fra IN elementene?

 

 

Lenke til kommentar
Videoannonse
Annonse
// REF http://stackoverflow.com/a/1705311/844397
IQueryable<Word> records = dbContext.WordTable.Select(r=> wordsToSearch.Contains(r));

System.Data.Common.DbCommand command = dbContext.GetCommand(records);

// bytt type fra "string" (nvarchar) til "ansistring" (varchar)
command.Parameters[0].DbType = DbType.AnsiString; 
command.Connection = dbContext.Connection;

//run
IEnumerable<Word> search = dbContext.Translate<Employee>(command.ExecuteReader());

Det beste jeg fant om temaet på det store internettet. Kan du teste det?

 

EDIT: Må si dette er en interessant problemstilling. Post løsning hvis/når du finner en!

Endret av Enthroner
Lenke til kommentar

Takker for alle inlegg folkens.  Dere var inne på det.  Det var snakk om datatype.  Utfordringen var at han som kodet domene klassene har bare brukt STRING over en lav sko for å representere tekst data uten å spesifisere hvilken.  Det jeg gjorde for å løse dette var faktisk veldig enkelt:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
  modelBuilder.Entity<TabellName>().Property(r => r.FeltMedString).HasColumnType("VARCHAR");
}

Og vips vaps vups - kjøre tiden ble dramatisk endret.  Nå kjører den samme spørringen på forventet tid

Lenke til kommentar

Takker for alle inlegg folkens.  Dere var inne på det.  Det var snakk om datatype.  Utfordringen var at han som kodet domene klassene har bare brukt STRING over en lav sko for å representere tekst data uten å spesifisere hvilken.  Det jeg gjorde for å løse dette var faktisk veldig enkelt:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
  modelBuilder.Entity<TabellName>().Property(r => r.FeltMedString).HasColumnType("VARCHAR");
}

Og vips vaps vups - kjøre tiden ble dramatisk endret.  Nå kjører den samme spørringen på forventet tid

 

Elegant og fin løsning :) 

Trodde du brukte LINQ to SQL, ikke EF - det gjør konfigurasjon lettere. Pent!

Lenke til kommentar

Opprett en konto eller logg inn for å kommentere

Du må være et medlem for å kunne skrive en kommentar

Opprett konto

Det er enkelt å melde seg inn for å starte en ny konto!

Start en konto

Logg inn

Har du allerede en konto? Logg inn her.

Logg inn nå
  • Hvem er aktive   0 medlemmer

    • Ingen innloggede medlemmer aktive
×
×
  • Opprett ny...