Using WCF Data Services with Entity Framework 4.1 and Code First


The information in this post is out of date.

Visit msdn.com/data/ef for the latest information on current and past releases of EF.


In this post you’ll see how Code First and the DbContext class in Entity Framework 4.1 RC will work with WCF Data Services going forward. WCF Data Services in .NET 4.0 was released prior to the Entity Framework 4.1 RC and so does not natively know about the DbContext class. There are numerous 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 class. This is not how we envisioned these technologies working together. However, it is possible to see how these technologies were meant to work together by using EF 4.1 RC along with the Microsoft WCF Data Services 2011 CTP2. In this walk through we’ll build a simple WCF Data Service using Code First with the latest and greatest releases. This post does assume some knowledge of Code First, DbContext, and WCF Data Services.

Getting Started

1. Download and install Microsoft WCF Data Services 2011 CTP2.

2. Open Visual Studio 2010 and create an ASP.NET Empty Web Application called “HospitalWeb”

3. Using the NuGet package manager, add the Entity Framework 4.1 RC to your project by installing the “EntityFramework” package.

Alternatively, you can download and install the full Entity Framework 4.1 RC setup. If you do this, you should add a reference to “EntityFramework.dll” in your project.

Create your data model

We’ll be using the Code First approach to build our data model and so will be using the DbContext API to help surface that. Here is what you need to do to your project:

1. Add a new code file to your project called “Model.cs”.

2. Add the following entity classes to your file:

public class Patient

{

    public int Id { get; set; }

       

    [MaxLength(64)]

    public string Name { get; set; }

    public virtual ICollection<LabResult> LabResults { get; set; }

}

public class LabResult

{

    public int Id { get; set; }

    public string Result { get; set; }

}

 

3. Add a DbContext class to your project. In this case, I’ve called mine HospitalContext.

public class HospitalContext : DbContext

{

    public DbSet<Patient> Patients { get; set; }

    public DbSet<LabResult> LabResults { get; set; }

}

 

 

4. You can also optionally add a Database initializer to your HospitalContext. One of the nice things about writing new applications with DbContext is that it can optionally create a database for you based on your .NET classes or entity data model, and also optionally pre-populate that database with seed data. Here is the initializer I am using:

public class HostpitalContextInitializer :

                 DropCreateDatabaseIfModelChanges<HospitalContext>

{

  protected override void Seed(HospitalContext context)

    {

        context.Patients.Add(new Patient { Name = "Fred Peters" } );

        context.Patients.Add(new Patient { Name = "John Smith" } );

        context.Patients.Add(new Patient { Name = "Karen Fredricks" } );

    }

}

To have your HospitalContext use this initializer, I added a static constructor to my HospitalContext with the method call to start using the initializer:

static HospitalContext()

{

    Database.SetInitializer(new HostpitalContextInitializer());

}

Your data model and context are now ready to be used with WCF Data Services. The first time a HospitalContext is created by our service, a database will be created for us and our seed data will be inserted.

Create your data service

The Microsoft WCF Data Services 2011 CTP2 did not include updated Visual Studio item templates, so I’ll show you how to use the existing item templates and fix them up to use the CTP:

1. Add a new project item to your HospitalWeb project, choosing “Web” and then “WCF Data Service” in the Visual Studio Add Project Item dialog. I called my service “HospitalService.svc”.

2. The WCF Data Service that was added to your project refers to .NET 4.0 only, not to CTP2, so we’ll need to make a few changes:

a. Remove the project references to “System.Data.Services” and “System.Data.Services.Client” from your project.

b. Add project to references “Microsoft.Data.Services” and “Microsoft.Data.Services.Client” from your project. Note that these assemblies are not installed in the GAC as part of WCF Data Services 2011 CTP2 installation, so you’ll need to browse to the installation directory to find them.

c. In your “HosptialService.svc.cs” file, change the service version from V2 to V3:

config.DataServiceBehavior.MaxProtocolVersion =

DataServiceProtocolVersion.V3;

Use your data model with your data service

Now you are ready to use your HospitalContext with your WCF Data Service. Here is all you need to do:

 

1. In your “HospitalService.svc.cs” file, change your HospitalService class to be a DataService<HospitalContext>:

public class HospitalService : DataService<HospitalContext>

2. Change the access permissions to the two sets of data we are interested in, Patients and LabResults:

public static void InitializeService(DataServiceConfiguration config)

{

    config.SetEntitySetAccessRule("Patients", EntitySetRights.AllRead);

    config.SetEntitySetAccessRule("LabResults", EntitySetRights.AllRead);

    config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V3;

}

3. You can also optionally add a service operation to your service to run custom queries and business logic using your HospitalContext. Below is a service operation method to retrieve all patients by name:

[WebGet]

public IQueryable<Patient> GetPatientsByName(string name)

{

    return CurrentDataSource.Patients.Where(p => p.Name.Contains(name));

}

 

Notice that CurrentDataSource is strongly typed to your HospitalContext, which is a DbContext instance from Entity Framework 4.1.

 

4. Finally, give permissions to your service operation in the InitializeService method:

config.SetServiceOperationAccessRule("GetPatientsByName",

                                         ServiceOperationRights.AllRead);

 

Run your service

You are now ready to run things. Go ahead and press F5. A bunch of things are going to happen:

1. Code First is going to build your data model using the Patient and LabResult classes.

2. The DbContext class is going to use that data model to create a database for you and populate it with our seed data.

3. A WCF Data Service is going to start up and display the metadata for the service

You can now try out a few WCF Data Services queries. Here are a few I played with:

1. Return all patients:

https://localhost:55051/HospitalService.svc/Patients/

2. Call the service operation GetPatientsByName and search for “Fred”:

https://localhost:55051/HospitalService.svc/GetPatientsByName?name='Fred'

 

As you can see, we’ve tried to make using the DbContext class and Code First seamless with DataServices. Both of the releases used in this post are in pre-release form, so if you find any issues with using them, using them together, or with the experience, please let us know!

Jeff Derstadt

Data Frameworks Team