views:

350

answers:

4

I've noticed that certain command cause LINQtoSQL to connect to the database and download the records that are part of the query, for example, .ToArray().

Does the command .Cast() cause a query to execute (and how can I tell these things in the future?). For example...

IRevision<T> current = context.GetTable(typeof(T))
    .Cast<IRevision<T>>()
    .SingleOrDefault(o => o.ID == recordId);

I know there is a command for .GetTable that allows you to specify a generic type, but for strange and unexplainable reasons, it cannot be used in this situation.

+2  A: 

From Enumerable.Cast()'s remarks:

This method is implemented by using deferred execution. The immediate return value is an object that stores all the information that is required to perform the action. The query represented by this method is not executed until the object is enumerated either by calling its GetEnumerator method directly or by using foreach in Visual C# or For Each in Visual Basic.

All of the LINQ operators will let you know if they are deferred execution or immediate query execution. Additionally, here are the standard LINQ operators which are NOT deferred:

  • Aggregate
  • All
  • Any
  • Average
  • Contains
  • Count
  • ElementAt
  • ElementAtOrDefault
  • First
  • FirstOrDefault
  • Last
  • LastOrDefault
  • LongCount
  • Max
  • Min
  • SequenceEqual
  • Single
  • SingleOrDefault
  • Sum
  • ToArray
  • ToDictionary
  • ToList
  • ToLookup
sixlettervariables
+1  A: 

No, it does not. It simply will perform a cast when you iterate through the IEnumerable.

There isn't any definitive way (in code) to know whether or not a method will use deferred execution or not. The documentation is going to be your best friend here as it will tell you if it defers execution or not.

However, that doesn't mean that you can't make some assumptions if the documentation is unclear.

If you have a method that returns another list/structure (like ToList, ToArray), then it will have to execute the query in order to populate the new data structure.

If the method returns a scalar value, then it will have to execute the query to generate that scalar value.

Other than that, if it simply returns IEnumerable<T>, then it more-than-likely is deferring execution. However, that doesn't mean that it's guaranteed, it just means it is more-than-likely.

casperOne
A: 

What you are looking for is called "Deferred Execution". Statements that defer execution only run when you attempt to access the data. Statements such as ToList execute immediately, as the data is needed to transform it into a list.

Cast can wait until you actually access it, so it is a deferred statement.

FlySwat
A: 

But why does simply casting a GetTable to an IEnumerable cause a query execution?

Example:

IEnumerable GetTable() { return dataContext.GetTable }

List GetAllBySomething(string something) { return (from t in GetTable() where t.something.Equals(something) select t).ToList(); }

When written like this, this executes essentially a "select * from table" upon calling GetTable and then does the query in the application instead of the db. If I get rid of GetTable() and call dataContext.GetTable in the LINQ itself, it makes the more appropriate "Select * from table where something = @p1" statement.

Huh? Is there any way around that?