entity framework - What's the difference(s) between .ToList(), .AsEnumerable(), AsQueryable()? -


i know differences of linq entities , linq objects first implements iqueryable , second implements ienumerable , question scope within ef 5.

my question what's technical difference(s) of 3 methods? see in many situations of them work. see using combinations of them .tolist().asqueryable().

  1. what methods mean, exactly?

  2. is there performance issue or lead use of 1 on other?

  3. why 1 use, example, .tolist().asqueryable() instead of .asqueryable()?

there lot this. let me focus on asenumerable , asqueryable , mention tolist() along way.

what these methods do?

asenumerable , asqueryable cast or convert ienumerable or iqueryable, respectively. cast or convert reason:

  • when source object implements target interface, source object returned cast target interface. in other words: type not changed, compile-time type is.

  • when source object not implement target interface, source object converted object implements target interface. both type , compile-time type changed.

let me show examples. i've got little method reports compile-time type , actual type of object (courtesy jon skeet):

void reporttypeproperties<t>(t obj) {     console.writeline("compile-time type: {0}", typeof(t).name);     console.writeline("actual type: {0}", obj.gettype().name); } 

let's try arbitrary linq-to-sql table<t>, implements iqueryable:

reporttypeproperties(context.observations); reporttypeproperties(context.observations.asenumerable()); reporttypeproperties(context.observations.asqueryable()); 

the result:

compile-time type: table`1 actual type: table`1  compile-time type: ienumerable`1 actual type: table`1  compile-time type: iqueryable`1 actual type: table`1 

you see table class returned, representation changes.

now object implements ienumerable, not iqueryable:

var ints = new[] { 1, 2 }; reporttypeproperties(ints); reporttypeproperties(ints.asenumerable()); reporttypeproperties(ints.asqueryable()); 

the results:

compile-time type: int32[] actual type: int32[]  compile-time type: ienumerable`1 actual type: int32[]  compile-time type: iqueryable`1 actual type: enumerablequery`1 

there is. asqueryable() has converted array enumerablequery, "represents ienumerable<t> collection iqueryable<t> data source." (msdn).

what's use?

asenumerable used switch iqueryable implementation linq objects (l2o), because former not support functions l2o has. more details see what effect of asenumerable() on linq entity?.

for example, in entity framework query can use restricted number of methods. if, example, need use 1 of our own methods in query typically write like

var query = context.observations.select(o => o.id)                    .asenumerable().select(x => mysupersmartmethod(x)) 

tolist – converts ienumerable<t> list<t> – used purpose well. advantage of using asenumerable vs. tolist asenumerable not execute query. asenumerable preserves deferred execution , not build useless intermediate list.

on other hand, when forced execution of linq query desired, tolist can way that.

asqueryable can used make enumerable collection accept expressions in linq statements. see here more details: do need use asqueryable() on collection?.

note on substance abuse!

asenumerable works drug. it's quick fix, @ cost , doesn't address underlying problem.

in many stack overflow answers, see people applying asenumerable fix problem unsupported methods in linq expressions. price isn't clear. instance, if this:

context.mylongwidetable // table many records , columns        .where(x => x.type == "type")        .select(x => new { x.name, x.createdate }) 

...everything neatly translated sql statement filters (where) , projects (select). is, both length , width, respectively, of sql result set reduced.

now suppose users want see date part of createdate. in entity framework you'll discover that...

.select(x => new { x.name, x.createdate.date }) 

...is not supported (at time of writing). ah, fortunately there's asenumerable fix:

context.mylongwidetable.asenumerable()        .where(x => x.type == "type")        .select(x => new { x.name, x.createdate.date }) 

sure, runs, probably. pulls entire table memory , applies filter , projections. well, people smart enough where first:

context.mylongwidetable        .where(x => x.type == "type").asenumerable()        .select(x => new { x.name, x.createdate.date }) 

but still columns fetched first , projection done in memory.

the real fix is:

context.mylongwidetable        .where(x => x.type == "type")        .select(x => new { x.name, dbfunctions.truncatetime(x.createdate) }) 

(but requires little bit more knowledge...)

what these methods not do?

now important caveat. when do

context.observations.asenumerable()                     .asqueryable() 

you end source object represented iqueryable. (because both methods cast , don't convert).

but when do

context.observations.asenumerable().select(x => x)                     .asqueryable() 

what result be?

the select produces whereselectenumerableiterator. internal .net class implements ienumerable, not iqueryable. conversion type has taken place , subsequent asqueryable can never return original source anymore.

the implication of using asqueryable not way magically inject query provider specific features enumerable. suppose do

var query = context.observations.select(o => o.id)                    .asenumerable().select(x => x.tostring())                    .asqueryable()                    .where(...) 

the condition never translated sql. asenumerable() followed linq statements definitively cuts connection entity framework query provider.

i deliberately show example because i've seen questions here people instance try 'inject' include capabilities collection calling asqueryable. compiles , runs, nothing because underlying object not have include implementation anymore.

specific implementations

so far, queryable.asqueryable , enumerable.asenumerable extension methods. of course can write instance methods or extension methods same names (and functions).

in fact, common example of specific asenumerable extension method datatableextensions.asenumerable. datatable not implement iqueryable or ienumerable, regular extension methods don't apply.


Comments

Popular posts from this blog

basic authentication with http post params android -

vb.net - Virtual Keyboard commands -

css - Firefox for ubuntu renders wrong colors -