Non-scalar Value Objects aka "Complex Types"
Yesterday there was a post on the ADO.Net Orcas forum asking if it is possible to map two entities to a single row in a single table using the entity framework. The motivation/scenario behind this request was an entity which had an address as part of its properties plus the fact that there were other entity types which have very similar properties. The default mapping generated by the wizard just adds these as properties of the entity, but the preferred model would be that the entity has a property which is another class that groups the address properties together. That class would then be shared and used to model the address properties on other entity types as well.
The initial expectation of the person asking the question was that the address should be modeled as an entity type of its own, but they ran into two problems:
- The address type doesn't have any appropriate property (or properties) to be its key.
- Even if you did have appropriate properties for the key, the system doesn't let you map two entities to the same row in the same table.
The moment I saw this post, I was reminded of a discussion I had with Atul Adya early on in the entity framework project when we were trying to decide whether or not to support a modelling concept we call "complex types". Initially we had hoped not to introduce another modelling concept--aren't scalars, entities and relationships enough? Atul's viewpoint on the matter was: "If we don't support complex types, then someday, someone is going to ask us to map two entities to the same row in the database, and we won't ever be able to support that." Well, here we are. At the moment the EF CTPs do not support complex types, and as a result someone has asked for the other feature Atul was referring to (two entities mapped to the same row) which we just can't support.
Why can't we support two entities mapped to the same row? Well, first off the lack of a property or properties that can be the key is fundamental. Secondly, if you think about it, what would insert and delete operations that affect one but not both of the entities in a row really mean? Things get crazy really quick.
So the answer is to make sure the EDM supports the idea of complex types which Eric Evans calls value objects in his Domain Driven Design book. They have no identity on their own--their identity is slaved to the entity of which they are a part, but they do get their own class where you can add methods, validation, etc. and share it among all instances of that value type regardless of which entity they are a part of.
Fortunately, we did decide to implement complex types, and they will appear in an upcoming CTP.