Avatar billede lasserasch Juniormester
08. januar 2013 - 11:28 Der er 4 kommentarer

Hjælp til at lave dette med Linq.

Hejsa.

Jeg har følgende stykke kode som virker og egentlig giver mig det resultat jeg ønsker. Men det er bare mega langsomt. (Det tager ca. 8 sekunder). Der ligger ca. 7500 records i mit datsæt, så det burde jo gå meget hurtigt.


  using (HSSQLDataContext dc = new HSSQLDataContext(Configuration.ConnectionString))
            {
                List<Municipality> result = new List<Municipality>();
                CheckSecurity(publickey, hash, dc);

                System.Linq.IQueryable<Hjertestarter> DbAeds = null;
                DbAeds = dc.Hjertestarters.Where(a => a.Statustypeid == Guid.Parse(Constants.IDs.InoperationID));

                foreach (Hjertestarter h in DbAeds)
                {
                    if (h.AEDKommune != null && h.AEDKommune.Kommune != null && h.AEDKommune.Kommune.nr != null)
                    {
                        if (result.FirstOrDefault(a => a.nr == h.AEDKommune.Kommune.nr) == null)
                            result.Add(new Municipality() { nr = h.AEDKommune.Kommune.nr, navn = h.AEDKommune.Kommune.navn, Region = h.AEDKommune.Kommune.region, NumberOfAED = 1 });
                        else
                            result.FirstOrDefault(a => a.nr == h.AEDKommune.Kommune.nr).NumberOfAED++;
                    }
                }
                return result;
            }



Egentlig kunne jeg godt tænke mig at lave det mere linq style.
Men jeg kan kun komme hertil :

  System.Linq.IQueryable<Hjertestarter> DbAeds = null;
              DbAeds = dc.Hjertestarters.Where(a => a.Statustypeid == Guid.Parse(Constants.IDs.InoperationID));
              return (from Kommune k in dc.Kommunes orderby k.navn select new Municipality { nr = k.nr, navn = k.navn, NumberOfAED = k.AEDKommunes.Count, Region = k.region }).ToList<Municipality>();


Denne kode virker sådan set også. Men som det ses i første kode eksempel, så indeholder DbAeds kun records med en bestemt status.

Og i mit resultat ønsker jeg at "NumberOfAED" kun indeholder antallet de hjertestartere som er aktive, og altså ligger i DbAeds datasættet.

Så det jeg vel har brug for er et eller andet inner select syntaks, som kan selecte antallet af hjertestartere ud af DbAeds som har samme .Aedkommune.Kommune.nr værdi.

Håber alt dette giver lidt mening.


I mit hoved ville det se nogenlunde sådan ud :

  return (from Kommune k in dc.Kommunes orderby k.navn select new Municipality { nr = k.nr, navn = k.navn, NumberOfAED = (from Hjertestarter h in DbAeds.Where(a => a.AEDKommune.Kommune.nr == k.nr)).Count(), Region = k.region }).ToList<Municipality>();

Men jeg har lidt problemer med at finde den rigtige syntaks :-)

Nogen som kan hjælpe?

Mvh.
Lasse
Avatar billede Syska Mester
08. januar 2013 - 13:02 #1
Hvorfor er det langsomt? Hvis det er pga mange lazy loads kan du så ikke bare hente alt data og så sortere på det efterfølgende in-memory.
Avatar billede lasserasch Juniormester
08. januar 2013 - 14:13 #2
Men hvordan henter man alt data med linq2sql?


Jeg har tilføjet lidt debug kode, og pt. set min kode sådan ud. Vedhæftet her, er også den debug mail som koden sender til mig.

Som det ses, så er det 'foreach' loopet som tager tiden.


public List<Municipality> GetMunicipalities(String publickey, String hash)
        {
            using (HSSQLDataContext dc = new HSSQLDataContext(Configuration.ConnectionString))
            {
                CheckSecurity(publickey, hash, dc);

                System.Linq.IQueryable<Hjertestarter> DbAeds = null;
                DbAeds = dc.Hjertestarters.Where(a => a.Statustypeid == Guid.Parse(Constants.IDs.InoperationID));

                List<Municipality> result = new List<Municipality>();
                CheckSecurity(publickey, hash, dc);

                System.Diagnostics.Stopwatch sw = System.Diagnostics.Stopwatch.StartNew();
                System.Diagnostics.Stopwatch sw2 = System.Diagnostics.Stopwatch.StartNew();
                DbAeds = dc.Hjertestarters.Where(a => a.Statustypeid == Guid.Parse(Constants.IDs.InoperationID));
                sw2.Stop();
                System.Diagnostics.Stopwatch sw3 = System.Diagnostics.Stopwatch.StartNew();
                foreach (Hjertestarter h in DbAeds.Where(a => a.AEDKommune != null & a.AEDKommune.Kommune != null & a.AEDKommune.Kommune.nr != null))
                {
                    if (result.FirstOrDefault(a => a.nr == h.AEDKommune.Kommune.nr) == null)
                        result.Add(new Municipality() { nr = h.AEDKommune.Kommune.nr, navn = h.AEDKommune.Kommune.navn, Region = h.AEDKommune.Kommune.region, NumberOfAED = 1 });
                    else
                        result.FirstOrDefault(a => a.nr == h.AEDKommune.Kommune.nr).NumberOfAED++;
                }
                sw3.Stop();

                sw.Stop();
                SendDebugMail("Det tog " + (sw.ElapsedMilliseconds) + " millisekunder at g¯re denne metode. Det tog " + sw2.ElapsedMilliseconds + " millisekunder at hente hjertestarter datasÊttet. Det tog " + sw3.ElapsedMilliseconds + "' millisekunder at k¯re foreach loop'et.");


                return result;
            }


        }






Her debug mail :

DDebug mail info: Det tog 17098 millisekunder at gøre denne metode. Det tog 0 millisekunder at hente hjertestarter datasættet. Det tog 17098' millisekunder at køre foreach loop'et. - 08-01-2013 14:04:42


Så jeg mistænker lidt at den laver en forespørgelse til databasen for hver af disse .Where() i foreach loopet.

foreach (Hjertestarter h in DbAeds.Where(a => a.AEDKommune != null & a.AEDKommune.Kommune != null & a.AEDKommune.Kommune.nr != null))

Linq må kunne noget her for at få afviklingstiden ned.
Avatar billede Syska Mester
08. januar 2013 - 14:25 #3
Hvis du kan, så smid LINQ2SQL på porten og skift til EntityFramework. L2S er død ...

Men derfor kan du stadig godt lave eager load med L2S... men da det er mange år siden jeg har brugt det, bliver jeg nød til at henvise til google: https://www.google.dk/#hl=da&gs_rn=1&gs_ri=hp&tok=k4iC3nmeqBgL1a25maGB8g&cp=11&gs_id=20&xhr=t&q=linq2sql+eager+load&pf=p&safe=off&tbo=d&output=search&sclient=psy-ab&oq=linq2sql+ea&gs_l=&pbx=1&bav=on.2,or.r_gc.r_pw.r_cp.r_qf.&bvm=bv.1357316858,d.Yms&fp=57440bb72ff88a74&biw=1920&bih=1075

http://www.hibernatingrhinos.com/products/L2SProf <- Er din ven i nød. Profiling og det hele ... der er en gratis trail af det. Så kan du se hvor mange lazy loads du får lavet :-)

mvh
Avatar billede janus_007 Nybegynder
08. januar 2013 - 21:47 #4
Jeg kan ikke lige 100% gennemskue din datamodel, men umiddelbart så.

CheckSecurity(publickey, hash, dc);
using(var context = new new HSSQLDataContext(Configuration.ConnectionString))
{
   
    var DbAeds = dc.Hjertestarters
                        .Where(a => a.Statustypeid == Guid.Parse(Constants.IDs.InoperationID)
                            && a.DbAeds.AEDKommune != null  // eller Any(x => x.AEDKommune != null)
                            && a.DbAeds.AEDKommune.Kommune != null // eller Any(.....)
                            && a.DbAeds.AEDKommune.Kommune.nr != null // eller Any(.....)
                        )
                        .Select(x => new Municipality{
                            NumberOfAed = x.Count()

                        });
}


Ellers smid DDL'erne til datamodellen :)
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
IT-kurser om Microsoft 365, sikkerhed, personlig vækst, udvikling, digital markedsføring, grafisk design, SAP og forretningsanalyse.

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester



IT-JOB

Udviklings- og Forenklingsstyrelsen

Data Engineers til bekæmpelse af skatteunddragelse

De Nationale Geologiske Undersøgelser for Danmark og Grønland (GEUS)

IT-systemadministrator søges til GEUS

Udviklings- og Forenklingsstyrelsen

Data Scientist til stærkt data- og analysekontor

Politiets Efterretningstjeneste

Bliv AD-specialist hos PET