The other day, my team and I ran into some design issues while trying to split a big Entity Framework model into smaller pieces according to areas of functionality. At first glance, it seemed to be a common design problem, something easy to overcome, but it did not result that way. I could not find much information about people having the same issue either.
In the system we are currently designing, we use modules or packages to group classes that belong to the same area of functionality. As you can guess, these modules do not represent more than a set of use cases or stories that are tightly coupled in design time.
We also have, however, some classes that are common for all those modules, so we put them in a shared module. In few words, we have a entity model shaped like a star, being the shared module the center of the star, and the rest of the modules just leafs.
The problem appeared when we tried to assign a different entity framework model to any of these modules for persisting the classes in a store. We could not find an easy way to reference the model with the shared entities from the rest of them, so we gave up after a while.
A single model with all the entities was not an option for us, because it simple does not scale up. We took a similar approach in the past with another project, the result was a huge model full of entities and really hard to maintain. This solution also required having a extra service layer on top of the entity model to encapsulate functionality specific to each module, which made very difficult to have a rich domain model at first glance.
After a search in several blogs, I came across this post "Working with large models in entity framework" from the Ado team, where they discuss some possible techniques or workarounds for an scenario like this.
They basically proposed the following solutions,
1. Reference one conceptual model (CSDL) from another. You create different models, and manually modify each CSDL to reference the model (CSDL) with the shared entities.
The CSDL model supports a clause "using" for including types defined in another model, it is basically a simple way to reuse types. This sounds good, however, it lacks of design time experience, which makes this feature totally useless for the scenario we have (and really complicated to implement according to this post written by Julie Lerman)
2. Duplicate metadata for the shared entities in each conceptual model (CSDL). Again, this approach sucks from a point of view of maintainability, typically you will have the same problems that you would see with duplicated code. One change in an shared entity will require changes in every model that reference it.
3. Expose foreign keys as scalar properties because you do not want to pull in all the shared entities into every Entity model. Not a good solution either, the shared entities get out of the unit of work or context (ObjectContext) generated by the designer. As result, you can not execute queries that require joins between the two contexts. Unless you include some helper methods to retrieve the shared entities using the scalar properties, you also lost the possibility of having a rich domain model.
As you can see, we could not find any workaround that totally met our expectations, so we might stick to the solution #2 (Duplicating the entities). The solution #1 would be perfect with some design time support, I hope the ado team consider this for a future release.
Do you have any thought or experience to share ?. I would be more than happy to hear your feedback regarding possible solutions for this scenario.