EF CTP4 Tips & Tricks: WCF Data Service on DbContext

Posted on July 19, 2010. Filed under: Entity Framework, Visual Studio | Tags: , , , , , , , |

This is the fourth in a series of posts about the recently released Entity Framework Feature CTP4, now affectionately known as “EF Magic Unicorn Edition”.

For this post I’m going to assume you are somewhat familiar with the Productivity Improvements for EF and WCF Data Services.

You can download the completed VS2010 project from this post.

Update: If you want to use DbContext with Dynamic Data then you can use a similar approach as described in this post by Stephen Naughton.

Existing ObjectContext Experience

If you’ve used WCF Data Services on top of Entity Framework before then you would have added a new Entity Data Model to your project, which in turn creates a derived ObjectContext class to allow you to query and persist data using the model. Then you would have added a WCF Data Service class that derives from a DataService of your derived ObjectContext, something like this:

using System.Data.Services;
using System.Data.Services.Common;

namespace PI.WCFDataService.Sample
{
    public class BlogService : DataService<BlogContext>
    {
        public static void InitializeService(DataServiceConfiguration config)
        {
            config.SetEntitySetAccessRule("Blogs", EntitySetRights.All);
            config.SetEntitySetAccessRule("Posts", EntitySetRights.All);
            config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V2;
        }
    }
}

What About DbContext?

Now what if your BlogContext derives from DbContext instead of ObjectContext? In the current CTP4 you can’t just create a DataService of a derived DbContext, although you can expect this to work by the time there is an RTM release.

But there is some good news, DbContext uses ObjectContext under the covers and you can get to the underlying context via a protected member. So lets define our derived context so that it exposes the context for our service to use:

using System.Data.Entity;
using System.Data.Objects;

namespace Service
{
    public class BlogContext : DbContext
    {
        public DbSet<Blog> Blogs { get; set; }
        public DbSet<Post> Posts { get; set; }

        public ObjectContext UnderlyingContext
        {
            get { return this.ObjectContext; }
        }
    }
}

Now all we need to do is create a DataService of ObjectContext and override the CreateDataSource method. In CreateDataSource we will construct a BlogContext and then return the underlying ObjectContext. Note that we also need to turn off proxy creation to allow WCF Data Services to function correctly.

using System.Data.Objects;
using System.Data.Services;
using System.Data.Services.Common;

namespace Service
{
    public class BlogService : DataService<ObjectContext>
    {
        public static void InitializeService(DataServiceConfiguration config)
        {
            config.SetEntitySetAccessRule("BlogSet", EntitySetRights.All);
            config.SetEntitySetAccessRule("PostSet", EntitySetRights.All);
            config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V2;
        }

        protected override ObjectContext CreateDataSource()
        {
            var ctx = new BlogContext();
            ctx.UnderlyingContext.ContextOptions.ProxyCreationEnabled = false;
            return ctx.UnderlyingContext;
        }
    }
}

 

That’s it, now WCF Data Services just thinks it’s interacting with a standard ObjectContext and everything works.

Entity Set Naming

If you are using the Code First capabilities of DbContext then your entity set names will be <ClassName>Set. Obviously this isn’t brilliant and is something that will improve in future releases. The likely solution is to use the name of the DbSet property that you defined on the derived context.

Virtual SaveChanges

One thing to note with this approach is that WCF Data Services is going to call SaveChanges on the underlying ObjectContext and not your derived context. This is only an issue if you have overridden SaveChanges in your derived context to include business logic because this logic won’t get executed when the Data Service persists changes to the database. There isn’t a workaround for this at the moment but the issue will go away once there is native support for DbContext in WCF Data Services.

Summary

You can use DbContext with WCF Data Services, it’s not 100% natively supported just yet but will be in the future. The code to get it to work is pretty simple and makes use of the underlying ObjectContext from your derived DbContext.

About these ads

Make a Comment

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

14 Responses to “EF CTP4 Tips & Tricks: WCF Data Service on DbContext”

RSS Feed for RoMiller.com Comments RSS Feed

Great post, Thanks!

Awesome awesome awesome! Thanks for sharing this, I was totally scratching my head in what to do here :)

Thanks so much for these non-obvious pointers!

I was wondering, does having to set the ‘ProxyCreationEnabled = false’ make using the DataService inefficient?

Is this something that is temporary for CTP, or a long term design feature?

Thanks!

@Phil Cockfield
Switching off Proxy Creation is just a temporary thing as WCF Data Services doesn’t support EF proxies at the moment, this is something that will be supported in the future though.

The performance difference between proxies on/off will depend on the scenario but in most cases there should be very minimal difference.

Cool – thanks Ro.

Fantastic. This is exactly the direction I’m going in.

Any ideas how to accomplish the same with RIA Services, instead of Data Services?

That makes GETs work just fine, but how about POST, PUT, and DELETEs. Attempting to perform a POST against the service yields:

The data source must implement IUpdatable or IDataServiceUpdateProvider to support updates

I tried your example and it worked just fine.

My problem was that I was returning my context from CreateDataSource instead of the ObjectContext. Doing that works.

-Damien

[...] Diego Vega posted on twitter a link to Rowan Millers blog EF CTP4 Tips & Tricks: WCF Data Service on DbContext this turned out to be very useful, he talks about getting the underlying ObjectContext see Listing [...]

EF CTP4 Tips & Tricks: WCF Data Service on DbContext « RoMiller.com…

Thank you for submitting this cool story – Trackback from DigItPort…

[...] error message led me to a comment on a post by Rowan Miller on using WCF Data Services against a DbContext, which is exactly what we were doing. Rowan points out that if you're going by experience or [...]

[...] posts already on how to get DbContext to work with WCF Data Services in .NET 4.0, including this one by Rowan Miller. These posts talk about how to write some extra code to initialize the DataService [...]

Rowan – thanks for the post, it helped me understand where my “disconnect” was…

Where you say “Obviously this isn’t brilliant and is something that will improve in future releases”… I would refer you to a post by Jon Galloway (http://weblogs.asp.net/jgalloway/archive/2011/01/21/fix-wcf-data-service-with-entity-framework-code-first-dbcontext-doesn-t-accept-updates.aspx?CommentPosted=true#commentmessage) in which he suggests there is a newer CTP5-esque way to accomplish this. However, I’m having no luck with his suggestion.

Any chance you could update your post for the current EF?

[...] posts already on how to get DbContext to work with WCF Data Services in .NET 4.0, including this one by Rowan Miller. These posts talk about how to write some extra code to initialize the DataService [...]


Where's The Comment Form?

    About

    Rowan works as a Program Manager for the ADO.NET Entity Framework team at Microsoft. He speaks at technical conferences and blogs at romiller.com. Rowan lives in Seattle, Washington with his wife Athalie. Prior to moving to the US he resided in the small state of Tasmania in Australia. Outside of technology Rowan's passions include snowboarding, mountain biking, horse riding, rock climbing and pretty much anything else that involves being active. The primary focus of his life, however, is to follow Jesus.

    RSS

    Subscribe Via RSS

    • Subscribe with Bloglines
    • Add your feed to Newsburst from CNET News.com
    • Subscribe in Google Reader
    • Add to My Yahoo!
    • Subscribe in NewsGator Online
    • The latest comments to all posts in RSS

    Meta

Liked it here?
Why not try sites on the blogroll...

Follow

Get every new post delivered to your Inbox.

Join 159 other followers

%d bloggers like this: