2

I have been developing an application for the last five months and just ran into this problem.

We are using EF5 and, similar to this question, I designed the class hierarchy to have all entity classes derived from an abstract base class to force validation interfaces to be implemented. We are also using the validation attributes in the entity classes.

Everything has worked fine until I started trying to use the entity classes in WCF Services. I am getting a bunch of serialization exceptions, and have been trying to figure out what "POCO" rule I broke in the design. This article tells me the class (obviously...) cannot be abstract, but since my classes are DERIVING from an abstract class, have I perhaps broken a rule I don't know about?

UPDATE: Here is the exception that I am struggling with:

System.Runtime.Serialization.SerializationException, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089

Type 'System.Data.Entity.DynamicProxies.WorkSession_63308485A9007DE087FF55AD9F246FD677863AA39AD56FEF4586AB87E21832DD' with data contract name 'WorkSession_63308485A9007DE087FF55AD9F246FD677863AA39AD56FEF4586AB87E21832DD:http://schemas.datacontract.org/2004/07/System.Data.Entity.DynamicProxies' is not expected. Consider using a DataContractResolver or add any types not known statically to the list of known types - for example, by using the KnownTypeAttribute attribute or by adding them to the list of known types passed to DataContractSerializer.

Community
  • 1
  • 1
Peter Howe
  • 429
  • 6
  • 19
  • Post the relevant exceptions messages. And no it has nothing to do with abstract base classes. – Federico Berasategui Sep 27 '13 at 19:19
  • Entity Framework dynamically creates classes that derive from yours, and those dynamically created classes are not designed for serialization. If you can live with the limitations of using only exactly the classes as you've defined them, you could mark your classes as `sealed` (edit: [or set `ProxyCreationEnabled` to false](http://stackoverflow.com/a/7277885/743382)), but that means no change tracking, no lazy loading, etc. as those features are implemented by overriding methods on your classes. –  Sep 27 '13 at 19:58
  • possible duplicate of [Serializable classes and dynamic proxies in EF - how?](http://stackoverflow.com/questions/7276507/serializable-classes-and-dynamic-proxies-in-ef-how) –  Sep 27 '13 at 20:01
  • "change tracking, [no] lazy loading, etc." - those are must-haves. So I take it that means we need to create a parallel set of DTO classes? :-( – Peter Howe Sep 27 '13 at 20:10
  • 1
    You disable change tracking and lazy loading *locally*, only for the particular query that loads the data before serialization, not generally for the whole project. Beyond the wire on client side you can't have EF features like change tracking and lazy loading anyway, so it's useless to send dynamic change tracking and lazy loading enabled entities over the wire. So, you won't lose any "must-haves". But using DTOs is still better for other reasons. – Slauma Sep 27 '13 at 20:21

2 Answers2

2

Since your POCOs use lazy loading, you don't get actual types from the EF but rather proxies so that navigation properties are auto implemented for lazy loading.

My advice is to forget the idea of exposing domain objects from web services. I bet there will be answers trying to convince you that this is possible in this particular case with a bunch of extra spells casted. However, the safest approach is to switch your thinking to DTOs, Data Transfer Objects, a pattern where you create an extra layer of "data-only" classes which are light and safe to serialize and send over the wire.

There are a lot of great articles explaining on how to expose your data using the DTO pattern and a couple of extra supporting technologies like the AutoMapper. You will find details easily and you can come back for further answers.

Wiktor Zychla
  • 47,367
  • 6
  • 74
  • 106
  • I started down the DTO route but then thought I could save us having a bunch of extra parallel classes, but seems I have no choice. Thanks for the answer! – Peter Howe Sep 27 '13 at 20:20
  • We cannot any new tools to the mix at this point (approval process, etc.), and the number of entities we need to support is limited for first release, so I have written a set of DTO classes, and we are good to go! Thanks! – Peter Howe Sep 30 '13 at 14:53
1

You didn't break a "POCO rule". The "dynamic proxy" mentioned in the exception is a class that is derived from your WorkSession entity, but it isn't derived in your code but dynamically at runtime. Entity Framework does this - by default - to make lazy loading and dynamic change tracking possible if you have marked your navigation properties (and maybe also scalar properties) as virtual.

You should disable dynamic proxy creation when you intend to serialize an entity with WCF. You can do this by simply setting a flag on the context before you load your entities from the database:

context.Configuration.ProxyCreationEnabled = false;

var worksessions = context.WorkSessions.....ToList();

The loaded worksessions are of the real runtime type WorkSession now, not of a dynamic proxy type and WCF shouldn't complain anymore.

Slauma
  • 175,098
  • 59
  • 401
  • 420