Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Entity Framework POCOs without behaviour - redesign needed to remove code smell

I am using Entity Framework Model-First with Repository and Unit of Work patterns, the repositories return EF POCOs.

I assumed that I couldn’t add behaviour to my POCOs that are generated by Entity Framework, so my code is now full of things like XyzService which is a separate class implementing the business logic for the Entity Framework generated Xyz POCO.

I have the following questions:

  1. This has a bad code smell as not only do I have the EF POCOs, I have a service for each POCO. In addition to lots of classes, business logic is split outside of the business entity. Is this an example of the anaemic anti-pattern?

  2. If I stick with EF, is there any way I can add behaviour (i.e. through partial classes) or other means?

  3. Seeing the persistent ignorant patterns which use return business entities from data layer (in our case a repository), if I wanted to go from EF-MODEL -> REPOSITORY-DAL -> BIZ-ENTITY I see there would be a lot of two way mapping between the business entity and the EF model POCO. Can utilities such as Automapper gracefully handle complex relationships of nested objects that I am likely to face?

  4. To reduce duplicated business entities with their counterpart EF model entities, would I not be better of removing EF and just writing my own repository implementations using LINQ to SQL for each repository?

  5. Any recommended way that allows me to concentrate on the code (rather than target fixating on the EF model first as I have been), then still use Entity Framework at the end when I am ready to write the persistence layer, but avoiding a lot of extra work and mapping in doing so? Would EF Code-First be better in this regard?

If I have missed anything else of other technologies that can aid development (NHibernate for example) then please feel free to mention.

like image 790
morleyc Avatar asked Dec 15 '12 18:12

morleyc


2 Answers

  1. Yeah, according to Fowler, this is an anti-pattern. I personally don't find this anti-pattern too offensive, but some people do. Use best judgement here. If it feels wrong and is a pain to deal with, then change it.
  2. Yes. Partial Classes can help with this. You can put behaviors in the partials you write.
  3. Yes, Automapper will automatically deal with nested objects if they have a mapping setup
  4. Again, thats up to you. If EF is driving you nuts, don't use it. Use what works and what makes you feel good while you use it.
  5. Code first was built for exactly this.
like image 182
Ryan Bennett Avatar answered Sep 19 '22 18:09

Ryan Bennett


  1. It is, but this approach isn't without advantages. For example, enforcing separation between the POCOs and the business logic could allow that logic to be decoupled and supplied via dependency injection or some other means.
  2. Keep in mind that partial classes cannot span multiple assemblies (from MSDN):

    All partial-type definitions meant to be parts of the same type must be defined in the same assembly and the same module (.exe or .dll file). Partial definitions cannot span multiple modules.

    This restriction could be undesirable, though you could instead use extension methods to implement the required behaviour.

  3. I've not used Automapper, so Ryan's advice would apply here.

  4. & 5. I have grouped these together as using Code-First would impact on your specific repository implementation. If you've not tried Code-First, I recommend taking a look at it.

In terms of repositories, my preference is for the repository to be completely generic in terms of both the POCO types we are dealing with, and the operations available. For example, with LINQ a repository could have a Get method that retrieves items (say, as an IEnumerable<T>) based upon a given Expression<Func<T, bool>>.

I like this approach because it allows the repository to be dependency injected, cleanly separates standard CRUD operations from more domain-specific ones, yet offers great opportunities for code reuse from consumers/derived classes.

like image 34
nick_w Avatar answered Sep 17 '22 18:09

nick_w