Linq extensions includes ToArray, ToList etc. All of these (including foreach etc...) run the query converting your IQueriable<t> into other data types.
You should build your IQueriable within your datamodel using partial classes. here is an example:
namespace myContextNamespace
{
public partial class Item
{
internal IQueriable<Item> Query(ContextDB db = null)
{
if(db==null)
db = new ContextDB();
return db.Items;
}
internal IQueriable<Item> QueryById(int id, ContextDB db = null)
{
if(db==null)
db = new ContextDB();
return Query(db).Where(i=>i.Id == id);
}
public List<Item> SelectAll(ContextDB db = null)
{
if(db==null)
db = new ContextDB();
return Query(db).ToList();
}
public Item SelectById(int id, ContextDB db = null)
{
if(db==null)
db = new ContextDB();
return QueryById(id,db).SingleOrDefault();
}
}
}
see how I keep the queriable as internal? I can use it in other partial classes in the case of conditional joins etc., but I always return the objects after executing the query.
In this case I may want to always exclude items with "ExpiredDate" not null. I simply change the queries like so:
namespace myContextNamespace
{
public partial class Item
{
internal IQueriable<Item> Query(ContextDB db = null)
{
if(db==null)
db = new ContextDB();
return QueryWithExpired(db).Where(i=>!i.ExpiredDate.HasValue);
}
internal IQueriable<Item> QueryWithExpired(ContextDB db = null)
{
if(db==null)
db = new ContextDB();
return db.Items;
}
internal IQueriable<Item> QueryById(int id, ContextDB db = null)
{
if(db==null)
db = new ContextDB();
return Query(db).Where(i=>i.Id == id);
}
public List<Item> SelectAll(ContextDB db = null)
{
if(db==null)
db = new ContextDB();
return Query(db).ToList();
}
public Item SelectById(int id, ContextDB db = null)
{
if(db==null)
db = new ContextDB();
return QueryById(id,db).SingleOrDefault();
}
}
}
Note how I have changed Query to exclude expired but kept an internal base query "QueryWithExpired". I will keep this in case I need to access them from another partial class in the future.
This was you can keep all your query logic within your datamodel and never expose an IQueriable outside of it.