Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

The impedance mismatch between EF and domain models: what is Entity Framework's answer? #4185

Closed
jnm2 opened this issue Dec 28, 2015 · 6 comments
Milestone

Comments

@jnm2
Copy link

jnm2 commented Dec 28, 2015

The object-relational impedance mismatch has gotten a lot of attention, but there is another kind of impedance: the mismatch between POCOs that are compatible with Entity Framework and POCOs that follow good domain modeling rules. A good domain model contains idioms such as:

  • Read-only properties
  • Encapsulated collections
  • Encapsulated primitives

Jimmy Bogard's Domain modeling with Entity Framework scorecard is a good analysis, and there are others.

Private setters on properties are a perfectly acceptable alternative to read-only properties, and I'm holding out hope for this issue which would give us encapsulated primitives. But when it comes to encapsulated collections, there aren't any clean options.

There are a range of workarounds for this mismatch. Vaughn Vernon's Modeling Aggregates with DDD and Entity Framework, exploring the use of interfaces as your domain model and ending up recommending the use of a state object in the domain model. That requires extra mapping. Jeremy Bogard's article looks at a custom ICollection implementation with [Obsolete] on mutation methods or simply leaving the domain model collections mutable to allow Entity Framework persistence.

For all these options, the domain model is modified and arguably compromised just for persistence concerns. Persistence concerns shouldn't truly be affecting the domain model. The default should just be to expose IReadOnlyCollection<> and IReadOnlyList<>.

What does Entity Framework hope to bring to this problem? Which method is currently recommended, and what is the path forward for encapsulated collections and primitives?

The thing Code First got amazingly right, POCOs, is that you aren't locked in to particular Entity Framework-specific idioms. You are free to model your entities to fit your application. Because of this impedance however, you are actually limited and even prevented from using good design principles in your entity models. This leads to a choice between rich model design with gyrations and mapping to force Entity Framework to work, or a poor model that works with Entity Framework out of the box. POCOs haven't reached their full potential.

Domain modeling is certainly not the only thing Entity Framework is used with, but it's growing. That's a good thing and it should be encouraged over anaemic models for the majority of projects which are not simple CRUD. Allowing Entity Framework to be a more powerful mapper so that it can be used out of the box with good model design will not interfere with Entity Framework's existing use cases; in fact, it will light up new possibilities across the board.

I ask that you would consider domain modeling as a possible central use case for Entity Framework to persist. At least, please consider lowering the barrier to domain driven design with Entity Framework and making good model design the pit of success.

@jbogard
Copy link

jbogard commented Dec 28, 2015

s/Jeremy Bogard/Jimmy Bogard

@rowanmiller
Copy link
Contributor

@jnm2 this is a good discussion, but it's a little too generic to be an actionable item that we leave around as an enhancement. To that end, I'd like to pull out the things that you are requesting. In general, the need for more flexibility around the shape of your POCOs is tracked by #240. That issue has links off to some more specific items, such as #857 which is about relaxing the requirements for collections. Are there any other specific improvements that you want in EF?

At the moment, I would solve this by having a private ICollection property that EF uses and then public Add/Remove methods that the application uses.

@jnm2
Copy link
Author

jnm2 commented Dec 31, 2015

@rowanmiller I understand. Is there a better place to have this discussion? I am hoping for higher-level recognition, actually, to specifically address the domain modeling scenario in such a way that it would be reflected in the purpose of EF. So that when you search for ways to use EF for domain modeling you end up on official EF wikis and samples showing the Entity-Framework-intended way to do good domain modeling. As of today, the only documentation to guide a potential DDD/EF user is a random assortment of tentative and incompatible blog posts by very intelligent people. New individual capabilities like #240 has may need to be implemented as part of that but there doesn't seem to be a strong, coherent story yet around good idiomatic domain modeling and that's what I'm hoping for.

As an example, I did a fair bit of searching for existing direction and didn't come across the issues you mentioned- probably because I was searching in the wrong terminology. What would be helpful would be a wiki page detailing the best way to build an EF-compatible domain model today, as well as what you want domain modeling to look like in the future and which issues to track to stay in the loop.

I am seriously excited for the future of EF7. It's almost too good to be true. You're taking the hard path with the most upside in so many other areas. Please consider domain modeling- something that lacks a truly compelling ORM solution today- as a central theme as you build the ORM to end all ORMs.


I would use the private ICollection property, except if I understand correctly it must be public or it's no good for eager loading or LINQ querying. EF needs to be able to recognize a readonly collection for eager loading and querying and map it to the private property. A private field convention would also be amazing:

private readonly List<Child> children = new List<Child>();
public IReadOnlyList<Child> Children => children.AsReadOnly();

Steve Smith worked around this by creating public Expression<Func<Parent, ICollection<Child>>> ChildMapping properties. EF shouldn't force that to be necessary- it's tedious and violates the principle that the domain model should be ignorant of the fact that is being persisted. Seems like this should be under #240.

@jbogard
Copy link

jbogard commented Dec 31, 2015

One thing to consider in this discussion is there's a difference between "persistence ignorance" and "I can take an object model and persist it to absolutely any SQL/NoSQL database". There will always be design compromises, whether from tooling or language e.g. "I can't have spaces in my method names?!? My domain experts always uses spaces between words!"

The preferences of the DDD community on how to implement DDD patterns changes over time. Vaughn's approach, effectively the Memento pattern, was also popular amongst NHibernate users because NHibernate naturally had constraints as well. That's why it's not really actionable to say "consider DDD domain modeling when designing EF". You've got to be very specific about a capability - mapping to members as private fields or collections as fields etc. Otherwise you're chasing a community where in 5 years we could all look back and say "boy wasn't THAT a dumb idea".

Finally, keep in mind that DDD originated in the time of heavy OOP and relational DBs. There are a lot of technical concepts that Evans himself reminds aren't nearly as important as the non-technical parts of the book. In fact, he indicated that if he had to write the book over again, the whole section on entities, aggregates etc would be an appendix. The important parts are language and modeling and strategic design. The rest are implementation details.

@rowanmiller rowanmiller added this to the Discussions milestone Dec 31, 2015
@rowanmiller
Copy link
Contributor

@jnm2 I'm happy to leave this open as a general discussion (moved it to the discussion milestone).

What would be helpful would be a wiki page detailing the best way to build an EF-compatible domain model today

Totally agree... we have a big list of docs to write before we'd get to that... but if someone who is more DDD focused wanted to take a stab it would be a great contribution to our docs (which are OSS too).

@ajcvickers
Copy link
Contributor

We are closing this issue because no further action is planned for this issue. If you still have any issues or questions, please log a new issue with any additional details that you have.

@ajcvickers ajcvickers reopened this Oct 16, 2022
@ajcvickers ajcvickers closed this as not planned Won't fix, can't repro, duplicate, stale Oct 16, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants