That's right. They can't be for a number of really good reasons including
- Serializer would follow down the navigation properties which at minimum means serializing enormous amounts of unrequested data and almost certainly leads to circular references with disasterous results.
- Many-to-many relationships don't serialize
- Serializer would invoke your custom properties unless you blocked them (leaving aside opt-in DataContract)
- Property invocation might execute code inside the properties (we could block execution of injection code ... but it's just another complication).
So how do we do it? We don't serialize the entities. We serialize the persistent data inside your entities. We do this for single entities and collections of entities. Our EntityCacheState provides this same mechanism to you.
We know where the data really are. We pull them out of the entities, push them into surrogate class instances, and THAT is what travels over the wire.
But you noticed that we have the [DataContract] attribute on our generated entity classes. Does that mean that they really are serializable?
Ah ... did you notice that there are no [DataMember] attributes on any of the members? DataContract serialization is opt-in. No member is serialized unless it is marked with [DataMember]. Traditional serialization (such as when marking a class [Serializable]) is opt-out; every property goes unless explictly excluded from serialization.
So if you tried to use DataContract serialization on our entities, none of whose members are marked with [DataMember], you'd get a big, fat nothing.
That's intentional ... and necessary! By marking the class with [DataContract], we prevent accidental .NET serialization - which would lead to all of the complications mentioned at the beginning of the post ... as we've learned the hard way.