Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Entity Framework, application layers and separation of concerns

I'm using the Entity Framework 4.1 and ASP.Net MVC 3 for my application. MVC provides the presentation layer, an intermediate library provides the business logic and the Entity Framework sort of acts as the data layer I guess?

I could separate the Entity Framework code into a set of repository classes, or an appropriate variation thereof, whatever constitutes a worthwhile data layer, but I'm having trouble resolving a design problem I have.

If the multi-layered approach exists to help me keep concerns separated, then it stands to reason that my choice of data persistence should also not be a concern of the presentation layer. The problem is that by using the Entity Framework, I'm basically tightly coupling my application to the notion that entity changes are tracked and persisted automatically.

As such, let's say in a hypothetical world I found a reason not to use the Entity Framework and wanted to swap it out. A well-designed solution should allow me to do this at the appropriate layer and not have dependent layers affected, but because all code is being written with the knowledge that the data layer tracks object changes, I would only be able to swap out the Entity Framework for something that works in a similar fashion, for example nHibernate.

How do I get to use the Entity Framework but not need to write my code in a way that assumes that entity changes are being tracked by the data layer?

UPDATE for those still wondering about this issue in their own scenarios:
Ayende Rahien wrote a great article shooting down this whole argument: http://ayende.com/blog/4567/the-false-myth-of-encapsulating-data-access-in-the-dal

like image 868
Nathan Ridley Avatar asked May 11 '11 17:05

Nathan Ridley


2 Answers

If you want to continue this way you should give up programming job and go to study philosophy. Entity framework is abstraction of persistence and there is a rule of Leaky abstraction which says that any non-trivial abstraction is to some degree leaky.

Agile methodologies come with really interesting phenomenon: Do not prepare for hypothetical situations. The most of the time it is just Gold plating. Each change has its cost. Changing persistence layer later in the project is costly but it is also very rare. From customer perspective there is no reason to pay part of these costs in the most of projects where this change is not needed. If we discus customer perspective more deeply we can say that he should not pay for that at all because choosing bad API which has to be replaced later on is failure of developers / architects. Refactor your code regularly but only to the point which is needed for adding new features which customer wants otherwise you can hardly be competitive on the market. This of course has some exceptions:

  • Customer wants (or architecture demands it for any reason and customer agrees with it) such abstraction. In such case you must count with it and define architecture open for such changes.
  • It is hobby or open source project where you can do what you want because it is not constrained by some resources

Now to your problem. If you want such high level abstraction you should not expose entities to your controller. Expose DTOs from the business layer (or even from repositories) and add fields like IsNew, IsModified, IsDeleted to those DTOs. Now your UI is completely separated from the persistence but your architecture is much more complex and there is probably no reason for such complexity - it is over architected. Another way can be simply turning off tracking (add AsNoTracking() to each query) and proxy creation on your entities (context.Configuration.ProxyCreationEnabled) - lazy loading will not work as well. That's like throwing away most of features persistence frameworks offer to you.

There are also other points of view. I recommend you reading Ayende's recent posts about repository and his comments to Sharp architecture.

like image 197
Ladislav Mrnka Avatar answered Nov 04 '22 01:11

Ladislav Mrnka


Short answer? You don't. You could turn off EF's tracking and then not worry about it, but that's about it.

If you're going to write your presentation layer with the expectation that changes are being tracked and persisted automatically, then whatever you replace EF with has to do that. You can't swap it out for something that doesn't track and persist changes automatically and just expect things to keep working. That'd be like taking a system that relies on a TCP/IP connection for duplex communication, swapping it to a HTTP connection (which by the nature of HTTP isn't really duplex) and expect things to work the same way. It doesn't.

If you want to be able to swap out your persistence layer for something else and not have to change anything else, then you need to wrap EF (or whatever) in your own custom code to provide the functionality you want. Then you have to provide implementations for anything not provided by whatever you swap to.

This is doable, but it's going to be an awful lot of work for a problem that very rarely actually happens. It's also going to add extra complexity to the project. Ladislav is bang on: it's not worth abstracting this far.

like image 2
Tridus Avatar answered Nov 04 '22 02:11

Tridus