EF 4.1 Code First and WCF Data Services Part 2: Service Operation Considerations

Note: The information provided in this post is now maintained in the TechNet Wiki topic: Using Entity Framework 4.1 Code First with WCF Data Services

In my previous post (Entity Framework 4.1: Code First and WCF Data Services), I demonstrated how to use the strongly-typed DbContext  from a Code First Northwind data model as the provider for a data service implementation. As you might recall from that post, WCF Data Services doesn’t know what to do with a DbContext (it expects EF providers that derive from ObjectContext), so we needed to manually override the CreateDataSource method and return the ObjectContext from the DbContext (NorthwindEntities in our Code First example).

This is all well and good for accessing feeds from the data service and executing queries, but (as one of my readers pointed out) there is an unexpected side-effect to our little trick. Because we provide the WCF Data Services runtime with an ObjectContext, the DataService<T>.CurrentDataSource property also returns an ObjectContext instead of the usual strongly-typed DbContext. Generally when using the EF provider, this method returns a strongly-typed ObjectContext, loaded with nice entity set properties that return IQueryable<T>. When creating service operations, this is a great way to query the EF model using the same (already open) EF connection and context.

Because the plain-old ObjectContext we get back from CurrentDataSource doesn’t have these nice code-generated properties, we again need to do a bit more work to access Code First entity sets in a service operation. The trick is to use the ObjectContext.GetObjectSet<T> method to access a specific entity set, as in the following example that returns a filtered set of Product entities:

// Service operation that returns non-discontinued products.
[WebGet]
public IQueryable<Product> GetCurrentProducts()
{
var context = this.CurrentDataSource;

    return context.CreateObjectSet<Product>()
.Where(p=>p.Discontinued == false)
.AsQueryable<Product>();
}

Note that the AsQueryable() method lets us return the entities as an IQueryable<T>, which enables clients to further compose the results of this service operation.

Cheers,

Glenn Gailey