DataContractSerializer error when using Entity Framework 4.0 with WCF 4.0

I am trying to get a list of objects from the Entity Framework through WCF, but I get the following exception:

An error occurred while trying to serialize the http://tempuri.org/:GetAllResult parameter. InnerException message was "Type 'System.Data.Entity.DynamicProxies.TestObject_240F2B681A782799F3A0C3AFBE4A67A7E86083C3CC4A3939573C5410B408ECCE' with data contract name 'TestObject_240F2B681A782799F3A0C3AFBE4A67A7E86083C3CC4A3939573C5410B408ECCE: http://schemas.datacontract.org/2004/07/System.Data.Entity.DynamicProxies ' is not expected to Consider using a DataContractResolver or add any types that are not statically known to the list of known types — for example, using the KnownTypeAttribute attribute or by adding them to the list of known types passed to the DataContractSerializer. 'For more information, see InnerException.

I used WCF in the past, but never used the Entity Framework. I have all my entities created through the Entity Framework and are annotated with the [DataContract] and [DataMember] attributes. I do not have navigation properties for any of my objects.

The GetAll () method is called in the abstract service class:

[ServiceContract] public interface IService<T> { [OperationContract] List<T> GetAll(); } 

And I use ChannelFactory to call my implementation:

 Binding binding = new NetTcpBinding(); EndpointAddress endpointAddress = new EndpointAddress("net.tcp://localhost:8081/" + typeof(TestObjectService).Name); using (ChannelFactory<ITestObjectService> channel = new ChannelFactory<ITestObjectService>(binding, endpointAddress)) { ITestObjectService testObjectService = channel.CreateChannel(); testObjects = testObjectService.GetAll(); channel.Close(); } 

I post it as such:

 Type type = typeof(TestObjectService); ServiceHost host = new ServiceHost(type, new Uri("http://localhost:8080/" + type.Name), new Uri("net.tcp://localhost:8081/" + type.Name)); host.Open(); 

When using debugging, it finds objects from the database, however it does not return objects.

Any ideas on where I might be wrong?

+54
entity-framework
Jul 30 '10 at 15:20
source share
5 answers

It was a pain to understand, but this is because EntityFramework creates the "proxy" of your class. The TestObject class that I had was configured correctly, but it created a class called: TestObject_240F2B681A782799F3A0C3AFBE4A67A7E86083C3CC4A3939573C5410B408ECCE

To make ChannelFactory + WCF + Entity Framework all together, you must go into your context constructor and add the following:

 ContextOptions.ProxyCreationEnabled = false; 

I hope this helps someone else.

+88
Jul 30 '10 at 15:49
source share

When using the DbContext API for Code First (EF 4.3), I had to do:

 public class MyClass : DbContext { public MyClass() { base.Configuration.ProxyCreationEnabled = false; } } 
+59
Feb 27 '12 at 16:21
source share

For EntityFramework 6.0, I also had to change the configuration:

 public class MyContext : DbContext { public MyContext() : base("name=MyContext") { Configuration.ProxyCreationEnabled = false; } } 
+15
Jan 25
source share

You have several other options besides adding a proxy server for the entire POCO:

1) Create a wrapper. In the API, most likely you do not want to expose all POCO to your users ... therefore, create a wrapper object that provides only what you need, and this also solves the proxy problem.

1.5) Pretty similar to 1, but instead of creating a wrapper, just return the anonymous type (with LINQ )

2) If you do not need to do this widely enough, it might make sense to do it in Controller , where you need this serialization ... or even more localized in Method , including using , here is the implementation for Controller :

 public class ThingController : ApiController { public ThingController() { db = new MyContext(); db.Configuration.ProxyCreationEnabled = false; } private MyContext db; // GET api/Thing public IQueryable<Thing> GetThings() { return db.Things; } //... protected override void Dispose(bool disposing) { if (disposing) db.Dispose(); base.Dispose(disposing); } } 

3) Another thing, if you only need this for this db call, the easiest way to do this is to associate AsNoTracking() with your call:

 List<Thing> things; using (var db = new MyContext()) { things = db.Things.AsNoTracking().ToList(); } 
+4
Jun 18 '15 at 5:25
source share

Instead, you can use DTO and return it. No need to disable the Proxycreationenabled property.

+1
Dec 03 '16 at 15:36
source share



All Articles