You’ve been asking for it for what seems like forever now, and as of today, it’s available.  That’s right, WCF RIA Services now supports EntityFramework Code First!  Varun Puranik developed the feature, and he has blogged about it, including some very useful Code Snippets.  I recommend going to read his post first, and then coming back here.

NuGet Baby!

EF Code First support for RIA Services is the first feature where we’re using NuGet as the first distribution mechanism.  Only NuGet offers the ability to release features independently from one another (without flooding your Add/Remove Programs list anyway), and it was a great fit for getting EF Code First support in your hands as quickly as possible.

The NuGet package is RIAServices.EntityFramework, and it depends on EntityFramework 4.1.  This can be used with WCF RIA Services V1.0 RTM, SP1, or SP2.  You can find SP1 and SP2 on our site.

We will also roll this feature into the WCF RIA Services Toolkit the next time we put out a release of the entire toolkit.

Heads-Up

With this release, there is no Domain Service Wizard support for your DbContext classes.  So when you do Add New Item and choose Domain Service Class, you won’t see your DbContext classes in the dialog.  But with the NuGet package and Varun’s VS Code Snippets, I suspect you won’t miss it much.  As Varun mentioned, we will be adding Domain Service Wizard support for your DbContext classes in WCF RIA Services V1.0 SP2.

There’s also a small gotcha that you need to be aware of.  In order to generate code into your Silverlight project, RIA Services has to inspect your DbContext at build time in order to get the entity types that are available.  If you have been using DbContext, you’re likely aware that simply creating and accessing a DbContext can actually create your database in SQL Express.  Chances are though, you don’t want this to happen at build time when RIA Services generates code.  In order to prevent this, there’s a small bit of code you need to add to your DbContext to null out your database initializer.  Varun illustrated this, and I’ll show it below too.

When using this feature, you will inevitably get a build warning along the lines of:

The attribute 'System.ComponentModel.DataAnnotations.DatabaseGeneratedAttribute' requires a reference to System.ComponentModel.DataAnnotations in the client project 'SilverlightApplication10'. Skipping generation of attribute. Please add a reference to System.ComponentModel.DataAnnotations to ensure generation of the attribute.

This is unavoidable at the moment, and you might have actually seen similar build warnings when using other DataAnnotations attributes that aren’t available in Silverlight.  This is where our code generation was trying to be smart, recognizing that your model has an attribute applied from the DataAnnotations namespace, but seeing that the attribute type isn’t available to your Silverlight project.  At the time we created that build warning messages, it was safe to assume this meant that you didn’t have a reference to DataAnnotations in your Silverlight project.  That is no longer true - EntityFramework 4.1 includes a DatabaseGeneratedAttribute type that is defined within the DataAnnotations namespace, but of course isn’t available in Silverlight.  You can just ignore this build warning.

Update:
Lastly, the day after we released this NuGet package, the Entity Framework team released a June CTP for EF.  That CTP is not yet supported for RIA Services.  We wanted to first get support in place for the released EntityFramework 4.1 bits, and we’ll work to target EntityFramework 4.2 as soon as we can.

Zero to Nifty in 5 Minutes

Let’s run through a super-quick-start for getting going with RIA Services and EF Code First.  This by no means is a guide to how to use EF Code First, but it illustrates how to use RIA Services with it in a basic example.

Before you begin, you must have WCF RIA Services (V1.0 RTM, SP1, or SP2) installed on your machine, as well as NuGet.

  1. File \ New Project \ Silverlight Application (or Silverlight Navigation Application, or Silverlight Business Application).
  2. If you selected Silverlight Application or Silverlight Navigation Application, check the “Enable WCF RIA Services” box
  3. Using your favorite gesture for adding NuGet packages, select and add ‘RIAServices.EntityFramework’ to your Web project
    • For instance, right-click on the Web project and select Manage NuGet Packages…
  4. Also add a NuGet package reference to ‘EntityFramework.Sample’ to get a sample blog model in your application
  5. Open the Models\BlogContext.cs class you got from EntityFramework.Sample and add a default constructor
    (this will only be needed until the next release of WCF RIA Services V1.0 SP2)

    public class BlogContext : DbContext {
    public DbSet<Post> Posts { get; set; }
    public DbSet<Comment> Comments { get; set; }

    public BlogContext()
    {
    // Prevent database initialization at design-time
    // when RIA Services is generating code
    if (HttpContext.Current == null)
    {
    Database.SetInitializer<BlogContext>(null);
    }
    }
    }

  6. Add a new class to your Web project using Add\Class… and name it BlogService.cs
  7. Make the class derive from DbDomainService<BlogContext>
  8. Add an [EnableClientAccess] attribute to the class
  9. Author your query, insert, update, and delete methods using the DbContext property on the DomainService, as well as the AttachAsModified extension method we provide.

    [EnableClientAccess]
    public class BlogService : DbDomainService<BlogContext>
    {
    public IQueryable<Post> GetPosts()
    {
    return this.DbContext.Posts.OrderByDescending(p => p.PublishDate).Take(5);
    }

    public void InsertPost(Post post)
    {
    DbEntityEntry<Post> entityEntry = this.DbContext.Entry(post);

    if ((entityEntry.State != EntityState.Detached))
    {
    entityEntry.State = EntityState.Added;
    }
    else
    {
    this.DbContext.Posts.Add(post);
    }
    }

    public void UpdatePost(Post post)
    {
    this.DbContext.Posts.AttachAsModified(post, this.ChangeSet.GetOriginal(post), this.DbContext);
    }

    public void DeletePost(Post post)
    {
    DbEntityEntry<Post> entityEntry = this.DbContext.Entry(post);

    if ((entityEntry.State != EntityState.Deleted))
    {
    entityEntry.State = EntityState.Deleted;
    }
    else
    {
    this.DbContext.Posts.Attach(post);
    this.DbContext.Posts.Remove(post);
    }
    }
    }

As far as RIA Services / EF Code First goes, you’re done.  At this point, you can now go into the Silverlight application and do all of the things you expect to do with RIA Services.  As with other DomainServices, your client has no awareness of what data access layer you’re using.  Because of this, you can use the new DbDomainService with Silverlight 4, Silverlight 5, or with RIA/JS.

Because we don’t have Domain Service Wizard support (until the next release of WCF RIA Service V1.0 SP2), you might want to grab Varun’s VS Code Snippets to make the above code simpler to crank out for each of your entity types.

How It Works

Thanks to the power or NuGet, quite a bit was actually done for you by adding the package reference to RIAServices.EntityFramework.

  1. Our NuGet package has a dependency on the EntityFramework 4.1 NuGet package, so that was installed for you.
  2. The NuGet package includes Microsoft.ServiceModel.DomainServices.EntityFramework, which added DbDomainService to the System.ServiceModel.DomainServices.EntityFramework namespace.  A reference to this assembly gets added.
  3. The NuGet package adds references to System.ServiceModel.DomainServices.Hosting and System.ServiceModel.DomainServices.Server
  4. The NuGet package transforms your web.config file to include the domainServices section definition, and the DomainServiceModule HTTP Module under both <system.web> and <system.webServer>

Note that 2-4 in this list matches up with what the Domain Service Wizard would typically do for you.  So even though we don’t have wizard support with the NuGet package, you still don’t have to mess with references or web.config to use RIA Services.