Archive
IQueryable, ObjectQuery and Composing LINQ to Entity Framework Queries
As discussed in a previous post, Entity Framework and WCF work very well together, but you need to be careful about LazyLoading being switched on automatically as this can serialise the entire object graph when querying via WCF which could have a very serious impact on performance.
With LazyLoading turned off however, the problem with WCF is how to bring back all the related data that is required. The answer is to use the ObjectQuery.Include method. In order to use this with LINQ you need to cast your IQueryableto an ObjectQuery.
This additionally allows you to compose queries from logical sections and finally include the additional extra entities that will be required in the results.
using (AdventureWorksLT2008Entities context = new AdventureWorksLT2008Entities()) { context.ContextOptions.LazyLoadingEnabled = false; // simple example to select some customers var customersQuery = from c in context.Customers where c.LastName.StartsWith("B") select c; // additional composition of the query which could be conditional var customersWithOrdersQuery = from c in customersQuery where c.SalesOrderHeaders.Count > 0 select c; // include the SalesOrderHeaders in the results var customerOrders = (customersWithOrdersQuery as ObjectQuery) .Include("SalesOrderHeaders"); foreach (Customer c in customerOrders) { Console.WriteLine("First Name: {0}, Last Name: {1}", c.FirstName, c.LastName); foreach (SalesOrderHeader soh in c.SalesOrderHeaders) { Console.WriteLine(" SalesOrderID: {0}, OrderDate: {1}, TotalDue: {2}", soh.SalesOrderID, soh.OrderDate, soh.TotalDue); } } }
Listing 1 – Example of composing queries and ObjectQuery<T>.Include
Entity Framework, LazyLoading & WCF
Entity Framework and WCF work well together in providing a good back end service layer for a range of application types. One gotcha however that can easily catch you out without being very visible is LazyLoading.
LazyLoading defers the loading of related entities, e.g. Order for Customers, until they are accessed via a navigation property.
In the Entity Framework runtime, the default value of the LazyLoadingEnabled property in an instance of an ObjectContext is false. However, if you use the Entity Framework tools to create a new model and the corresponding generated classes, LazyLoadingEnabled is set to true in the object context’s constructor.
Thus it is possible for LazyLoading to be enabled without really explicitly requesting the feature.
There is no problem with this and LazyLoading is a great feature if you are not using WCF, however the serialisation of objects to XML before being sent over the wire causes all the navigation properties to be accessed throughout the model and thus it is very easy to accidentally serialise the whole object graph which consequently has the effect of slowing down the data access via WCF.
LazyLoading can be switched of explicitly in the ObjectContext using the code below or for Entity Framework as a whole by changing the properties of the EDMX.
public void QueryWithoutLazyLoading() { using (AdventureWorksEntities context = new AdventureWorksEntities()) { context.ContextOptions.LazyLoadingEnabled = false; ... } }
Listing 1 – Disabling LazyLoading on the ObjectContext
In the next post I’ll look at how to work around not using LazyLoading with WCF as well as how to build up queries in manageable chunks that can be specialised based on logic.