TechNet
Products
IT Resources
Downloads
Training
Support
Products
Windows
Windows Server
System Center
Microsoft Edge
Office
Office 365
Exchange Server
SQL Server
SharePoint Products
Skype for Business
See all products »
Resources
Channel 9 Video
Evaluation Center
Learning Resources
Microsoft Tech Companion App
Microsoft Technical Communities
Microsoft Virtual Academy
Script Center
Server and Tools Blogs
TechNet Blogs
TechNet Flash Newsletter
TechNet Gallery
TechNet Library
TechNet Magazine
TechNet Wiki
Windows Sysinternals
Virtual Labs
Solutions
Networking
Cloud and Datacenter
Security
Virtualization
Updates
Service Packs
Security Bulletins
Windows Update
Trials
Windows Server 2016
System Center 2016
Windows 10 Enterprise
SQL Server 2016
See all trials »
Related Sites
Microsoft Download Center
Microsoft Evaluation Center
Drivers
Windows Sysinternals
TechNet Gallery
Training
Expert-led, virtual classes
Training Catalog
Class Locator
Microsoft Virtual Academy
Free Windows Server 2012 courses
Free Windows 8 courses
SQL Server training
Microsoft Official Courses On-Demand
Certifications
Certification overview
Special offers
MCSE Cloud Platform and Infrastructure
MCSE: Mobility
MCSE: Data Management and Analytics
MCSE Productivity
Other resources
Microsoft Events
Exam Replay
Born To Learn blog
Find technical communities in your area
Azure training
Official Practice Tests
Support options
For business
For developers
For IT professionals
For technical support
Support offerings
More support
Microsoft Premier Online
TechNet Forums
MSDN Forums
Security Bulletins & Advisories
Not an IT pro?
Microsoft Customer Support
Microsoft Community Forums
Sign in
Home
Library
Wiki
Learn
Gallery
Downloads
Support
Forums
Blogs
Resources For IT Professionals
United States (English)
Россия (Pусский)
中国(简体中文)
Brasil (Português)
Skip to locale bar
Editing: Using Entity Framework 4.1 Code First with WCF Data Services
Wiki
>
TechNet Articles
>
Using Entity Framework 4.1 Code First with WCF Data Services
Article
History
Title
<p>The Entity Framework 4.1 release introduced a feature named Code First, which enables you to define an Entity Framework data model using only code. For more information, see <a href="http://msdn.microsoft.com/en-us/library/gg696194(v=VS.103).aspx"><span style="color: #0066dd;">Getting Started with the Entity Framework 4.1</span></a>. This article shows you how to create a Code First implementation of Northwind, which is then used as the data source by <a href="http://msdn.microsoft.com/en-us/library/cc668792.aspx"><span style="color: #0066dd;">WCF Data Services</span></a> to create a Northwind data service that supports the <a href="http://www.odata.org/"><span style="color: #0066dd;">Open Data Protocol (OData)</span></a>. The code in this topic has been verified using Entity Framework 4.1 and .NET Framework 4 version of WCF Data Services.</p> <h2><a name="Code_First_as_an_Entity_Framework_Data_Service_Provider"></a>Code First as an Entity Framework Data Service Provider</h2> <p>Code First introduces a new class to manage entities, the <a href="http://msdn.microsoft.com/en-us/library/system.data.entity.dbcontext(v=VS.103).aspx"><span style="color: #0066dd;">DbContext</span></a> class. This new context class uses an underlying <a href="http://msdn.microsoft.com/en-us/library/system.data.objects.objectcontext(v=VS.103).aspx"><span style="color: #0066dd;">ObjectContext</span></a> instance. However, because <a href="http://msdn.microsoft.com/en-us/library/system.data.entity.dbcontext(v=VS.103).aspx"><span style="color: #0066dd;">DbContext</span></a> does not inherit from <a href="http://msdn.microsoft.com/en-us/library/system.data.objects.objectcontext(v=VS.103).aspx"><span style="color: #0066dd;">ObjectContext</span></a>, it can not be used directly by WCF Data Services as an <a href="http://msdn.microsoft.com/en-us/library/dd673932.aspx"><span style="color: #0066dd;">Entity Framework provider</span></a>. Instead, you must manually obtain the underlying <a href="http://msdn.microsoft.com/en-us/library/system.data.objects.objectcontext(v=VS.103).aspx"><span style="color: #0066dd;">ObjectContext</span></a> from the <a href="http://msdn.microsoft.com/en-us/library/system.data.entity.infrastructure.iobjectcontextadapter.objectcontext(v=VS.103).aspx"><span style="color: #0066dd;">IObjectContextAdapter.ObjectContext</span></a> implementation and provide this context to the WCF Data Service runtime by overriding the <a href="http://msdn.microsoft.com/en-us/library/cc646746.aspx"><span style="color: #0066dd;">CreateDataSource</span></a> method.</p> <table border="1" cellpadding="10"> <tbody> <tr> <td><span style="font-size: 11px;"><strong>Note</strong>: WCF Data Services 5.0 now supports the direct use of the <a href="http://msdn.microsoft.com/en-us/library/system.data.entity.dbcontext(v=VS.103).aspx"><span style="color: #0066dd;">DbContext</span></a> class as an Entity Framework provider. You can download this release, which also supports OData v3, from the <a href="http://go.microsoft.com/fwlink/?LinkID=248279">WCF Data Services 5.0 download page</a>. </span></td> </tr> </tbody> </table> <p>This example assumes that you have the following installed:</p> <ul> <li>Visual Studio 2010 – includes .NET Framework 4 </li> <li>Entity Framework 4.1 or 4.2 – you can get Entity Framework 4.1 from the <a href="http://go.microsoft.com/fwlink/p/?LinkId=207115"><span style="color: #0066dd;">Microsoft Download Center</span></a> or as a <a href="http://go.microsoft.com/fwlink/?LinkId=232287"><span style="color: #0066dd;">NuGet package</span></a>) </li> <li>(Optional) Northwind database –if you do not already have Northwind installed on your default SQL Server Express instance, then Code First will create a new Northwind Instance for you, but this new Northwind instance will not contain any of the Northwind data. </li> </ul> <p>To see the complete source code for this example, download the <a href="http://go.microsoft.com/fwlink/?LinkId=221310"><span style="color: #0066dd;">project from MSDN Code Gallery</span></a>. </p> <h5><a name="To_create_the_Code_First_Northwind_Data_Model"></a>To create the Code First Northwind Data Model:</h5> <ol> <li>In Visual Studio, create a new ASP.NET Web application project. </li> <li>Add references to the following assemblies: <ul> <li>EntityFramework.dll –the Entity Framework 4.1 assembly. </li> <li>System.ComponentModel.DataAnnotations.dll –defines some of the mapping attributes </li> </ul> </li> <li>Create a new code page in the project and add the following set of Code First Northwind classes: <blockquote>[Table("Customers")] <br /> public class Customer <br /> { <br /> public string CustomerID { get; set; } <br /> public string CompanyName { get; set; } <br /> public string ContactName { get; set; } <br /> public string ContactTitle { get; set; } <br /> public string Address { get; set; } <br /> public string City { get; set; } <br /> public string Region { get; set; } <br /> public string PostalCode { get; set; } <br /> public string Country { get; set; } <br /> public string Phone { get; set; } <br /> public string Fax { get; set; } <br /> public virtual ICollection<Order> Orders { get; set; } <br /> } <br /> [Table("Employees")] <br /> public class Employee <br /> { <br /> public int EmployeeID { get; set; } <br /> public string LastName { get; set; } <br /> public string FirstName { get; set; } <br /> public string Title { get; set; } <br /> public string TitleOfCourtesy { get; set; } <br /> public DateTime? BirthDate { get; set; } <br /> public DateTime? HireDate { get; set; } <br /> public string Address { get; set; } <br /> public string City { get; set; } <br /> public string Region { get; set; } <br /> public string PostalCode { get; set; } <br /> public string Country { get; set; } <br /> public string HomePhone { get; set; } <br /> public string Extension { get; set; } <br /> public byte[] Photo { get; set; } <br /> public string Notes { get; set; } <br /> public int? ReportsTo { get; set; } <br /> public string PhotoPath { get; set; } <br /> [ForeignKey("ReportsTo")] <br /> public virtual Employee Manager{ get; set; } <br /> public virtual ICollection<Order> Orders { get; set; } <br /> } <br /> [Table("Order Details")] <br /> public class OrderDetail : IValidatableObject <br /> { <br /> [Key, Column(Order = 1)] <br /> public int OrderID { get; set; } <br /> [Key, Column(Order = 2)] <br /> public int ProductID { get; set; } <br /> public decimal UnitPrice { get; set; } <br /> public short Quantity { get; set; } <br /> public float Discount { get; set; } <br /> public Order Orders { get; set; } <br /> [ForeignKey("ProductID")] <br /> public virtual Product Product { get; set; } <p> // Validate for the Discount property. <br /> public IEnumerable<ValidationResult> Validate(ValidationContext validationContext) <br /> { <br /> <br /> if (Discount < 0 || Discount > 1) <br /> { <br /> yield return new ValidationResult <br /> ("Discount must be a value between zero and one", new[] { "Discount" }); <br /> } <br /> } <br /> } <br /> [Table("Orders")] <br /> public class Order <br /> { <br /> public int OrderID { get; set; } <br /> public string CustomerID { get; set; } <br /> public int? EmployeeID { get; set; } <br /> public DateTime? OrderDate { get; set; } <br /> public DateTime? RequiredDate { get; set; } <br /> public DateTime? ShippedDate { get; set; } <br /> public decimal? Freight { get; set; } <br /> public string ShipName { get; set; } <br /> public string ShipAddress { get; set; } <br /> public string ShipCity { get; set; } <br /> public string ShipRegion { get; set; } <br /> public string ShipPostalCode { get; set; } <br /> public string ShipCountry { get; set; } <br /> [ForeignKey("CustomerID")] <br /> public virtual Customer Customer { get; set; } <br /> [ForeignKey("EmployeeID")] <br /> public virtual Employee Employee { get; set; } <br /> public virtual ICollection<OrderDetail> OrderDetails { get; set; } <br /> //public Shipper Shipper { get; set; } <br /> } <br /> [Table("Products")] <br /> public class Product <br /> { <br /> public int ProductID { get; set; } <br /> public string ProductName { get; set; } <br /> public string QuantityPerUnit { get; set; } <br /> public decimal? UnitPrice { get; set; } <br /> public short? UnitsInStock { get; set; } <br /> public short? UnitsOnOrder { get; set; } <br /> public short? ReorderLevel { get; set; } <br /> public bool Discontinued { get; set; } <br /> // public Category Category { get ; set;} <br /> public ICollection<OrderDetail> Order_Detail { get; set; } <br /> // public Supplier Suppliers { get ; set;} <br /> } </p> </blockquote> </li> <li>Define the context class, named <strong>NorthwindContext</strong>, that inherits from <a href="http://msdn.microsoft.com/en-us/library/system.data.entity.dbcontext(v=VS.103).aspx"><span style="color: #0066dd;">DbContext</span></a>, as follows: <blockquote>public class NorthwindContext : DbContext <br /> { <br /> public DbSet<Customer> Customers { get; set; } <br /> public DbSet<Employee> Employees { get; set; } <br /> public DbSet<Order> Orders { get; set; } <br /> public DbSet<OrderDetail> OrderDetails { get; set; } <br /> public DbSet<Product> Products { get; set; } <br /> }</blockquote>This context class exposes properties that return typed-DbSet properties for each entity set, which are exposed as OData feeds by the data service. </li> <li>Add the following new connection string named <strong>NorthwindEntities</strong> to the project’s Web.config file: <br /> <blockquote> <p><add name="NorthwindEntities" connectionString="Data Source=.\SQLExpress;Initial Catalog=Northwind;Integrated <br /> Security=True;MultipleActiveResultSets=True" providerName="System.Data.SqlClient"/></p> </blockquote>This is a named SqlClient connection string that targets an existing Northwind database, in this case on the local SQL Express instance. <br /> Skip this step when you have Code First create the database instance for you. </li> <li>Add the following constructor to the <strong>NorthwindContext</strong> class: <br /> <blockquote> <p>// Use the constructor to target a specific named connection string <br /> public NorthwindContext() <br /> : base("name=NorthwindEntities") <br /> { <br /> // Disable proxy creation, which doesn’t work well with data services. <br /> this.Configuration.ProxyCreationEnabled = false;</p> <p> // Create Northwind if it doesn't already exist. <br /> this.Database.CreateIfNotExists(); <br /> }</p> </blockquote>This constructor is needed to target a named connection string. </li> <li>(Optional) add the following <a href="http://msdn.microsoft.com/en-us/library/system.data.entity.dbcontext.onmodelcreating(v=vs.103).aspx"><span style="color: #0066dd;">OnModelCreating</span></a> method override to the <strong>NorthwindContext</strong> class: <br /> <blockquote> <p>// Disable creation of the EdmMetadata table. <br /> protected override void OnModelCreating(DbModelBuilder modelBuilder) <br /> { <br /> modelBuilder.Conventions.Remove<IncludeMetadataConvention>(); <br /> }</p> </blockquote>This prevents the creation of the EdmMetadata table in the database. You only need to do this when you use “*” in the <a href="http://msdn.microsoft.com/en-us/library/system.data.services.dataserviceconfiguration.setentitysetaccessrule.aspx"><span style="color: #0066dd;">SetEntitySetAccessRule</span></a> method, which is not recommended a recommended practice. </li> </ol> <h5><a name="To_create_a_Northwind-based_OData_service_that_uses_the_Code_First_Northwind_Model"></a>To create a Northwind-based OData service that uses the Code First Northwind Model:</h5> <ol> <li>In <strong>Solution Explorer</strong>, right-click the ASP.NET project, and then click <strong>Add New Item</strong>. </li> <li>In the <strong>Add New Item</strong> dialog box, select <strong>WCF Data Service</strong>. </li> <li>For the name of the service, type <strong>Northwind</strong>. </li> <li>In the Northwind.svc.cs file, which is the code-behind page for the data service, replace the generated <strong>Northwind</strong> data service class with the following code: <blockquote>public class Northwind : DataService<ObjectContext> <br /> { <br /> // This method is called only once to initialize service-wide policies. <br /> public static void InitializeService(DataServiceConfiguration config) <br /> { <br /> // Explicitly define permissions on the exposed entity sets. <br /> config.SetEntitySetAccessRule("Customers", EntitySetRights.AllRead); <br /> config.SetEntitySetAccessRule("Employees", EntitySetRights.AllRead); <br /> config.SetEntitySetAccessRule("Orders", EntitySetRights.All); <br /> config.SetEntitySetAccessRule("OrderDetails", EntitySetRights.All); <br /> config.SetEntitySetAccessRule("Products", EntitySetRights.AllRead); <br /> config.DataServiceBehavior.MaxProtocolVersion = <br /> DataServiceProtocolVersion.V2; <br /> } <br /> } </blockquote>Note that the type of the data service is <a href="http://msdn.microsoft.com/en-us/library/system.data.objects.objectcontext"><span style="color: #0066dd;">ObjectContext</span></a> and not <strong>NorthwindContext</strong>; the current released version of WCF Data Services does not recognize <a href="http://msdn.microsoft.com/en-us/library/system.data.entity.dbcontext(v=VS.103).aspx"><span style="color: #0066dd;">DbContext</span></a> as an Entity Framework provider, so you need to manually provide the base <a href="http://msdn.microsoft.com/en-us/library/system.data.objects.objectcontext"><span style="color: #0066dd;">ObjectContext</span></a> class to the data service. </li> <li>Add the following <a href="http://msdn.microsoft.com/en-us/library/cc646746.aspx"><span style="color: #0066dd;">CreateDataSource</span></a> method override to the <strong>Northwind</strong> data service class: <blockquote>// We must override CreateDataSource to manually return an ObjectContext, <br /> // otherwise the runtime tries to use the built-in reflection provider <br /> // instead the Entity Framework provider. <br /> protected override ObjectContext CreateDataSource() <br /> { <br /> NorthwindContext nw = new NorthwindContext(); <br /> <br /> // Get the underlying ObjectContext for the DbContext. <br /> var context = ((IObjectContextAdapter)nw).ObjectContext; <br /> context.ContextOptions.ProxyCreationEnabled = false; <br /> <br /> // Return the underlying context. <br /> return context; <br /> } </blockquote></li> </ol> <p>At this point, you should be able to run your Northwind data service.</p> <h2><a name="Service_Operation_Considerations"></a>Service Operation Considerations</h2> <p>When you create a service operation, it is common to use the underlying Entity Framework provider to access the database directly by using the Entity Framework with the existing connection. You do this by getting the strongly-typed <a href="http://msdn.microsoft.com/en-us/library/system.data.objects.objectcontext"><span style="color: #0066dd;">ObjectContext</span></a> from the <a href="http://msdn.microsoft.com/en-us/library/cc646632.aspx"><span style="color: #0066dd;">DataService<T>.CurrentDataSource</span></a> property. However, as a side-effect of manually providing the WCF Data Services runtime with the <a href="http://msdn.microsoft.com/en-us/library/system.data.objects.objectcontext"><span style="color: #0066dd;">ObjectContext</span></a> from a Code First provider, the <a href="http://msdn.microsoft.com/en-us/library/cc646632.aspx"><span style="color: #0066dd;">DataService<T>.CurrentDataSource</span></a> property returns an un-typed <a href="http://msdn.microsoft.com/en-us/library/system.data.objects.objectcontext"><span style="color: #0066dd;">ObjectContext</span></a> instead of a strongly-typed <a href="http://msdn.microsoft.com/en-us/library/system.data.entity.dbcontext(v=VS.103).aspx"><span style="color: #0066dd;">DbContext</span></a>, which include the <a href="http://msdn.microsoft.com/en-us/library/gg696460(v=vs.103).aspx"><span style="color: #0066dd;">DbSet<TEntity></span></a> properties that implement the nice <a href="http://msdn.microsoft.com/en-us/library/bb351562.aspx"><span style="color: #0066dd;">IQueryable<T></span></a> functionality. Since the data service does not have access to this strongly-typed <a href="http://msdn.microsoft.com/en-us/library/system.data.entity.dbcontext(v=VS.103).aspx"><span style="color: #0066dd;">DbContext</span></a>, we must instead call the <a href="http://msdn.microsoft.com/en-us/library/dd382944.aspx"><span style="color: #0066dd;">ObjectContext.CreateObjectSet<TEntity></span></a> method to manually get an <a href="http://msdn.microsoft.com/en-us/library/dd412719.aspx"><span style="color: #0066dd;">ObjectSet(TEntity)</span></a>, which also implements <a href="http://msdn.microsoft.com/en-us/library/bb351562.aspx"><span style="color: #0066dd;">IQueryable<T></span></a>. </p> <p>The following example creates a service operation that returns a filtered set of Product entities:</p> <blockquote></blockquote> <blockquote> <p>// Service operation that returns non-discontinued products. <br /> [WebGet] <br /> public IQueryable<Product> GetCurrentProducts() <br /> { <br /> var context = this.CurrentDataSource;</p> <p> return context.CreateObjectSet<Product>() <br /> .Where(p=>p.Discontinued == false) <br /> .AsQueryable<Product>(); <br /> }</p> </blockquote> <p>Note that the <a href="http://msdn.microsoft.com/en-us/library/bb507003.aspx"><span style="color: #0066dd;">AsQueryable()</span></a> method lets us return the entities as an <a href="http://msdn.microsoft.com/en-us/library/bb351562.aspx"><span style="color: #0066dd;">IQueryable<T></span></a>, which enables clients to further compose the results of this service operation.</p>
Comment
Tags
Please add 1 and 5 and type the answer here: