[LINQ] IQueryable vs IENumerable

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • PdeBie
  • Registratie: Juni 2004
  • Laatst online: 18:19
Hoi allemaal,

ik ben momenteel bezig met een project waarbij we gebruik maken van LINQ to SQL.
Tijdens de ontwikkeling merkte iemand op dat ik gebruik maak van IENumerable ipv IQueryable, terwijl ik beter van IQueryable gebruik kan maken. Echter op mijn vraag 'waarom dan?' wist hij geen duidelijk antwoord te verschaffen.

Op internet zelf lees ik ook eigenlijk alleen maar 'if you use LINQtoSQL you should use IQueryable'. Maar geen redenering hiervoor.

Iemand hier die mij duidelijk kan maken waarom dit is? Performance redenen misschien?
Want mijn applicatie werkt verder naar behoren met de IENumerables. En als ik van de IENumerables 'IQueryables' wil maken, moet ik daar een behoorlijke tijd in gaan steken, wat ik liever niet doe als de verschillen minimaal zijn.

Acties:
  • 0 Henk 'm!

  • Avalaxy
  • Registratie: Juni 2006
  • Laatst online: 18:33

Acties:
  • 0 Henk 'm!

  • P-Storm
  • Registratie: September 2006
  • Laatst online: 10:02
Pin me er niet op vast, en kan best mis zijn maar is het dat IENumerables de actie gelijk uitvoeren en de IQueryable pas wanneer een andere variabele het antwoord nodig heeft.

Met de link van google van de voorganger :)
The primary difference is that the extension methods defined for IQueryable<T> take Expression objects instead of Func objects, meaning the delegate it receives is an expression tree instead of a method to invoke. IEnumerable<T> is great for working with in-memory collections, but IQueryable<T> allows for a remote data source, like a database or web service. I walk through these differences in this article: C# 3.0 and LINQ.

Acties:
  • 0 Henk 'm!

  • Niemand_Anders
  • Registratie: Juli 2006
  • Laatst online: 09-07-2024

Niemand_Anders

Dat was ik niet..

Een IEnumerable voert acties direct uit, terwijl een IQueryable de acties kan verzamelen en als een instructie kan uitvoeren.

C#:
1
2
IEnumerable<User> users = db.Users.List();
var x = users.Where(x => x.Email == "someone@example.org").OrderBy(x => x.Username).Take(5);

Deze zal alle akties apart uitvoeren terwijl eenzelfde selectie via een IQueryable een sql statement als
select top 5 * from users where Email='someone@example.org' order by Username zal opleveren.

IEnumerable werkt direct op een collectie, terwijl een IQueryable werkt op een expression tree.

[ Voor 0% gewijzigd door RobIII op 22-03-2011 21:47 . Reden: Code tags gefixed :P Prutz0r :P ]

If it isn't broken, fix it until it is..


Acties:
  • 0 Henk 'm!

  • beany
  • Registratie: Juni 2001
  • Laatst online: 19:44

beany

Meeheheheheh

pdebie schreef op dinsdag 22 maart 2011 @ 13:42:
Hoi allemaal,

ik ben momenteel bezig met een project waarbij we gebruik maken van LINQ to SQL.
Even niet ingaand op je echte vraag, maar Linq to sql wordt eigenlijk afgeraden tegenwoordig. Kijk eens naar Entity Framework 4.1: MSDN: ADO.NET Entity Framework

Werkt een stuk beter, meer manieren om zaken op te lossen etc etc.

Dagelijkse stats bronnen: https://x.com/GeneralStaffUA en https://www.facebook.com/GeneralStaff.ua


Acties:
  • 0 Henk 'm!

  • PdeBie
  • Registratie: Juni 2004
  • Laatst online: 18:19
Niemand_Anders schreef op dinsdag 22 maart 2011 @ 13:57:
Deze zal alle akties apart uitvoeren terwijl eenzelfde selectie via een IQueryable een sql statement als
select top 5 * from users where Email='someone@example.org' order by Username zal opleveren.

IEnumerable werkt direct op een collectie, terwijl een IQueryable werkt op een expression tree.
Dus performance technisch gezien kan ik beter gebruik maken van een IQueryable, omdat ik niet wil dat hij 2x de datasource aanroept ivm grote collecties.

@beany: thanks. Zal dit eens doorlezen.

Acties:
  • 0 Henk 'm!

  • EfBe
  • Registratie: Januari 2000
  • Niet online
beany schreef op dinsdag 22 maart 2011 @ 14:00:
[...]

Even niet ingaand op je echte vraag, maar Linq to sql wordt eigenlijk afgeraden tegenwoordig. Kijk eens naar Entity Framework 4.1: MSDN: ADO.NET Entity Framework

Werkt een stuk beter, meer manieren om zaken op te lossen etc etc.
Linq to sql heeft een veel betere Linq provider en is sneller dan EF. Het zit in .net, en gaat er ook echt niet meer uit. Roepen dat het EF beter is vind ik op zijn zachtst gezegd nogal voorbarig.
Niemand_Anders schreef op dinsdag 22 maart 2011 @ 13:57:
Een IEnumerable voert acties direct uit, terwijl een IQueryable de acties kan verzamelen en als een instructie kan uitvoeren.

[code=c#)
IEnumerable<User> users = db.Users.List();
var x = users.Where(x => x.Email == "someone@example.org").OrderBy(x => x.Username).Take(5);
[/code]
Deze zal alle akties apart uitvoeren terwijl eenzelfde selectie via een IQueryable een sql statement als
select top 5 * from users where Email='someone@example.org' order by Username zal opleveren.

IEnumerable werkt direct op een collectie, terwijl een IQueryable werkt op een expression tree.
Omdat IQueryable ook een IEnumerable is is het bovenstaande wellicht wat verwarrend. Zie het als volgt:
var q = context.Customer.Where(c=>c.Country=="NL");

dit roept de 'Where' extension method aan op het object dat de property 'Customer' teruggeeft. Is 'Customer' een IQueryable, dan zal de Where() extension method van IQueryable worden aangeroepen. Deze extension method zal een expression tree aanmaken, met een method call expression naar de where method en zn arguments.

Is 'Customer' een property die alleen maar een IEnumerable teruggeeft, dan wordt de Where extension method van IEnumerable aangeroepen. Deze extension method voert de method meteen uit (door een enumerator terug te geven, ipv een expression tree).

Deze verwarring is overigens wel de basis van veel fouten in linq queries: men ziet vaak niet welke delen in memory en in de database worden uitgevoerd.

[ Voor 56% gewijzigd door EfBe op 22-03-2011 14:25 ]

Creator of: LLBLGen Pro | Camera mods for games
Photography portfolio: https://fransbouma.com


Acties:
  • 0 Henk 'm!

  • beany
  • Registratie: Juni 2001
  • Laatst online: 19:44

beany

Meeheheheheh

EfBe schreef op dinsdag 22 maart 2011 @ 14:21:
[...]

Linq to sql heeft een veel betere Linq provider en is sneller dan EF. Het zit in .net, en gaat er ook echt niet meer uit. Roepen dat het EF beter is vind ik op zijn zachtst gezegd nogal voorbarig.
Het zal er ook niet uit gaan, maar EF heeft wel voordelen ten opzichte van L2S. Het is met 4.1 een stuk volwassener geworden. Al schort het nog wel een beetje aan documentatie.

En dat L2S sneller is: ik heb nog geen testjes gedaan, ik heb ook nog geen testjes online gezien. En vaak is het met een business app ook zo dat de voordelen van een uitgebreid framework het performance nadeel niet van belang maakt.

Dagelijkse stats bronnen: https://x.com/GeneralStaffUA en https://www.facebook.com/GeneralStaff.ua


Acties:
  • 0 Henk 'm!

  • PdeBie
  • Registratie: Juni 2004
  • Laatst online: 18:19
EfBe schreef op dinsdag 22 maart 2011 @ 14:21:
Deze verwarring is overigens wel de basis van veel fouten in linq queries: men ziet vaak niet welke delen in memory en in de database worden uitgevoerd.
Nee, dit is mij inderdaad ook niet altijd even duidelijk, maar aangezien ik met redelijk grote collecties werk moet ik hier wel rekening mee houden. Echter is dit mijn eerste project met LINQ, dus is het voor mij ook nog allemaal nieuw. :)

Acties:
  • 0 Henk 'm!

  • HMS
  • Registratie: Januari 2004
  • Laatst online: 21-08 23:06

HMS

beany schreef op dinsdag 22 maart 2011 @ 14:00:
[...]

Even niet ingaand op je echte vraag, maar Linq to sql wordt eigenlijk afgeraden tegenwoordig. Kijk eens naar Entity Framework 4.1: MSDN: ADO.NET Entity Framework

Werkt een stuk beter, meer manieren om zaken op te lossen etc etc.
Ja, of NHibernate natuurlijk. Geweldige ORM :*)

Maargoed, volgens mij is het verschil tussen een IEnumerable<T> en een IQueryable<T> wel duidelijk.

Acties:
  • 0 Henk 'm!

  • Grijze Vos
  • Registratie: December 2002
  • Laatst online: 28-02 22:17
Niemand_Anders schreef op dinsdag 22 maart 2011 @ 13:57:
Een IEnumerable voert acties direct uit, terwijl een IQueryable de acties kan verzamelen en als een instructie kan uitvoeren.
Dit is niet juist. Een IEnumerable maakt ook gewoon gebruik van lazy loading, pas op het moment dat je gaat itereren wordt er iets uitgevoerd.

Op zoek naar een nieuwe collega, .NET webdev, voornamelijk productontwikkeling. DM voor meer info


Acties:
  • 0 Henk 'm!

  • R4gnax
  • Registratie: Maart 2009
  • Laatst online: 06-09 17:51
Grijze Vos schreef op dinsdag 22 maart 2011 @ 15:08:
[...]

Dit is niet juist. Een IEnumerable maakt ook gewoon gebruik van lazy loading, pas op het moment dat je gaat itereren wordt er iets uitgevoerd.
Precies dit is dan ook de bron van heel veel bugs. Deferred execution is in het algemeen goed voor performance, omdat je alleen code draait voor die sequences die ook daadwerkelijk ge-enumereerd worden, maar oh jeeh als je geen rekening houdt met bijvoorbeeld variabelen die uit closures komen.

Het wordt nog leuker als je gebruik maakt van home-cooked LINQ extensies die dit principe niet 100% honoreren. Krijg je van die leuke situaties zoals guard clausules (null argument, argument out of range, etc.) die wel je invoer als valide zien, maar waarbij later (in het defered execution gedeelte) het toch nog fout gaat.

LINQ is eigenlijk een behoorlijk complex stukje techniek wat door veel mensen zonder achtergrondkennis van de principes opgepikt is. Jammer genoeg betekend dat dat 9/10e v/h web weer eens niet weet waar ze het over hebben: het PHP syndroom.

Ik kan heel erg het blog van John Skeet aanraden, die met EduLINQ een complete her-implementatie van de bestaande LINQ operators heeft gemaakt, compleet met argumentatie en uitleg over achterliggende principes.


[rant]
Het sneue is trouwens dat er als pleister op de wond dan weer zo'n idiote stroming ontstaan is die aanhoudt dat alles meteen ToList() gedaan moet worden. Tuurlijk jongens; gooi alle mogelijke performance winst (incl. alles wat PLINQ met ToParallel kan doen!) maar meteen overboord omdat een paar kneuzen het niet snappen. |:(
[/rant]

[ Voor 18% gewijzigd door R4gnax op 22-03-2011 20:30 ]


Acties:
  • 0 Henk 'm!

  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
Ik kan me vergissen maar ik méén me te herinneren dat Bart de Smet op de PDC10 een interessant stuk over IQueryable v.s. IEnumerable had. Ik heb helaas niet de tijd om door de hele video te scrubben, maar volgens mij is dit dan wel 't bekijken waard. Is het niet 't geval dan mea culpa; misschien steek je er iets anders van op :) Maar dan moet 't (if my mind serves me correctly) toch écht 1 van de andere PDC10 video's zijn...
Aaaargh; ik haat 't als ik niet meer weet waar ik iets interessants heb gezien... :X

Then again is 't in dit topic inmiddels ook wel aardig uitgelegd :Y)

[ Voor 22% gewijzigd door RobIII op 22-03-2011 21:51 ]

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij


Acties:
  • 0 Henk 'm!

  • PdeBie
  • Registratie: Juni 2004
  • Laatst online: 18:19
Ik heb een aantal testjes gemaakt met IEnumerables en IQueryables en in mijn geval bleek de IQueryable qua performance 3x zo snel als de IEnumerable. Keuze snel gemaakt dus :)

Dank voor de info allemaal!

Acties:
  • 0 Henk 'm!

  • Grijze Vos
  • Registratie: December 2002
  • Laatst online: 28-02 22:17
R4gnax schreef op dinsdag 22 maart 2011 @ 20:25:
[...]

[rant]
Het sneue is trouwens dat er als pleister op de wond dan weer zo'n idiote stroming ontstaan is die aanhoudt dat alles meteen ToList() gedaan moet worden. Tuurlijk jongens; gooi alle mogelijke performance winst (incl. alles wat PLINQ met ToParallel kan doen!) maar meteen overboord omdat een paar kneuzen het niet snappen. |:(
[/rant]
heh, wij hebben dat bij een paar van onze LLBLGen (2.6, dat wel) moeten doen omdat we een paar gare onoplosbare bugs hadden. vooral van het type:

code:
1
2
from p in products
select CreateProductDTO(p);


Kregen we continue vage bugs op. Ik vermoed dat het in 3.0 gefixed is, maar wij gaan zelf waarschijnlijk toch over op een andere O/R mapper, dus niet de moeite waard om en nieuwe versie aan te schaffen.

Op zoek naar een nieuwe collega, .NET webdev, voornamelijk productontwikkeling. DM voor meer info

Pagina: 1