Assume we have a method like this:
public IEnumerable<T> FirstMethod() { var entities = from t in context.Products where {some conditions} select t; foreach( var entity in entities ) { entity.SomeProperty = {SomeValue}; yield return entity; } }
where context is a DataContext that is generated by Linq to SQL designer.
Does ‘FirstMethod’ load the data into memory from database (because of the foreach loop) or will it still defer-load it until another foreach loop that doesn’t have ‘yield return’ is found in another method like the following?
public void SecondMethod() { foreach( var item in FirstMethod() ) { {Do Something} } }
The latter (deferred);
FirstMethodis an iterator block (because ofyield return); this means that you have a chain of iterators. Nothing is read until the final caller starts iterating the data; then each record is read in turn during the final caller’sforeach(between which the connection/command is open).The
usingthat surroundsforeach(under the bonnet) ensures that the connection is closed if theforeachis abandoned half-way-through.If you want to load the data earlier, use
.ToList()or.ToArray()to buffer the data locally – but note that this breaks ‘composition’ – i.e. the caller can no longer add extraWhereetc clauses (which they can if it returns a rawIQueryable<T>).Re your question:
The
AsEnumerableis the key here; it ends the composableIQueryable<T>chain, and uses LINQ-to-Objects for the rest.