Click here to Skip to main content
Click here to Skip to main content

Using EF DbContext with WCF Data Services

By , 11 Dec 2010
 

Introduction

One of the questions that you may ask yourself with the new EF feature CTP5 is how Using DbContext with WCF Data Servicesto embed the new DbContext object inside an OData service or more particularly inside WCF Data Service. This post will supply the solution.

DbContext as WCF Data Service Data Source

Entity Framework has a good integration with WCF Data Services. All you need to do when you create a WCF Data Service with EF is to put the generated ObjectContexts a data source of the service. The following code is a simple WCF Data Service on top of EF ObjectContext

public</span /> class</span /> SchoolDataService : DataService<SchoolEntities>
{
  public</span /> static</span /> void</span /> InitializeService(DataServiceConfiguration config)
  {
    config.SetEntitySetAccessRule("</span />*"</span />, EntitySetRights.AllRead);
 
    config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V2;
  }
}

When you will try to do the same with DbContext, you will get a surprise. The service will run but when you will try to query the data it exposes, you will get an error like the following:

The XML page cannot be displayed 
Cannot view XML input using XSL style sheet. 
Please correct the error and then click the Refresh button, or try again later. 

-------------------------------------------------------------------------------
The following tags were not closed: feed. 
Error processing resource 'http://localhost:29753/SchoolDataService.svc/Courses'. 

The reason for the error is because currently DbContextnd WCF Data Services integration isn’t working well. So what can we do for now?
Since the DbContexts a wrapper for the ObjectContextwe can expose the ObjectContexttself. In order to do that, you will have to override the CreateDataSourceethod of the service and return the ObjectContextThe following example shows a simple WCF Data Service that uses the DbContext’ve created in the previous post about EF Feature CTP fluent API:

[ServiceBehavior(IncludeExceptionDetailInFaults=true)]
public</span /> class</span /> SchoolDataService : DataService<ObjectContext>
{
  public</span /> static</span /> void</span /> InitializeService(DataServiceConfiguration config)
  {
    config.SetEntitySetAccessRule("</span />*"</span />, EntitySetRights.AllRead);
 
    config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V2;
  }
 
  protected</span /> override</span /> ObjectContext CreateDataSource()
  {     
    var</span /> context = ((IObjectContextAdapter)new</span /> SchoolEntities()).ObjectContext;      
    context.ContextOptions.ProxyCreationEnabled = false</span />;      
    return</span /> context;    
  }    
}

A few things to notice:

  • In the CreateDataSourceI cast the DbContexto an interface it implements – IObjectContextAdapterThis interface exposes an ObjectContextroperty which is the underlying context wrapped by the DbContext
  • You must disable proxy creation because in service scenarios you mustn't use the change tracking and lazy loading behaviors that are created through runtime proxies.

Summary

DbContextntegration with WCF Data Services isn’t supported currently. In order to have a working workaround for that, you can use the underling ObjectContexthich the DbContextrap. Hopefully in the near future, this workaround won’t be needed and we will have integration out of the box.


License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Gil Fink
Architect Sela Group
Israel Israel
Member
Gil Fink is an expert in ASP.NET and Microsoft data platform and serves as a Senior Architect at SELA Group. He is a Microsoft data platform MVP and a certified MCPD Enterprise Application Developer. Gil has worked in the past in variety of positions and projects as a leading developer, team leader, consultant and more. His interests include Entity Framework, Enterprise Library, WCF, LINQ, ADO.NET and many other new technologies from Microsoft.
 

My technical blog: http://www.gilfink.net

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
GeneralMy vote of 5membermohsenbz11 Apr '12 - 21:08 
thank you
GeneralCTP5&WCF Data Services don't mix well :(memberDotNetWise11 Dec '10 - 6:50 
I've just tried that and it works.
But if you try to do any $select=SomeProperty it crashes ugly with this error:
{
-error: {
code: ""
-message: {
lang: "en-GB"
value: "Not Implemented"
}
-innererror: {
message: "Unable to create a constant value of type 'System.Data.Services.Internal.ProjectedWrapper2'. Only primitive types ('such as Int32, String, and Guid') are supported in this context."
type: "System.NotSupportedException"
stacktrace: " at System.Data.Objects.ELinq.ExpressionConverter.ConstantTranslator.TypedTranslate(ExpressionConverter parent, ConstantExpression linq) at System.Data.Objects.ELinq.ExpressionConverter.TranslateExpression(Expression linq) at System.Data.Objects.ELinq.ExpressionConverter.ConditionalTranslator.TypedTranslate(ExpressionConverter parent, ConditionalExpression linq) at System.Data.Objects.ELinq.ExpressionConverter.TranslateLambda(LambdaExpression lambda, DbExpression input) at System.Data.Objects.ELinq.ExpressionConverter.TranslateLambda(LambdaExpression lambda, DbExpression input, DbExpressionBinding& binding) at System.Data.Objects.ELinq.ExpressionConverter.MethodCallTranslator.SelectTranslator.Translate(ExpressionConverter parent, MethodCallExpression call) at System.Data.Objects.ELinq.ExpressionConverter.MethodCallTranslator.TypedTranslate(ExpressionConverter parent, MethodCallExpression linq) at System.Data.Objects.ELinq.ExpressionConverter.TranslateExpression(Expression linq) at System.Data.Objects.ELinq.ELinqQueryState.GetExecutionPlan(Nullable`1 forMergeOption) at System.Data.Objects.ObjectQuery`1.GetResults(Nullable`1 forMergeOption) at System.Data.Objects.ObjectQuery`1.System.Collections.Generic.IEnumerable<T>.GetEnumerator() at System.Data.Entity.Infrastructure.DbQuery`1.System.Collections.IEnumerable.GetEnumerator() at System.Data.Services.Internal.ProjectedWrapper.EnumerableWrapper.GetEnumerator() at System.Data.Services.WebUtil.GetRequestEnumerator(IEnumerable enumerable)"
}
}
}

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web04 | 2.6.130523.1 | Last Updated 11 Dec 2010
Article Copyright 2010 by Gil Fink
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid