andree
andree

Reputation: 3224

How/where to put business logic to EF entities when dependencies are required?

I'm trying to write some business logic for my app. At the core of my app are EF generated entities from Database First model. I have separated generated classes (.tt file ) from .edmx part.

I want to find the best place where to put my business logic, but the problem is, that business logic requires some complicated dependencies, for example, needs logging, calls some WebService, or makes pure SQL calls to DB. Because of that, I can't just use new() inside functions and create hard dependencies, but I want to somehow abstract away from them, following DI principles.

public class Person
{
    public Person(IDbCaller dbCaller, IWebServiceCaller webServiceCaller) { }
}

My first bet was to use partial classes, that extend EF classes.

But after reading some articles, I am now thinking that injecting dependencies into EF classes is not a good idea:

Why not use an IoC container to resolve dependencies for entities/business objects?

http://lostechies.com/jimmybogard/2010/04/14/injecting-services-into-entities/

So, where should I put this logic? I agree, that dependencies on EF entities are bad, but I cant really find solutions. Logic needs to be somewhere. I see a few options/questions:

1) Put business logic (that requires dependencies) inside Service layers. This could lead to Anemic Domain Model, but maybe Service layers are the right place for this kind of logic, that requires dependencies?

2) Create some king or Wrapper/Factory classes, that I need to call every time query returns entities, so I can wrap entity with business logic.

3) Put that logic inside some other classes, that take entity as a function parameter.

What are some good, common practices for this?

Upvotes: 3

Views: 2434

Answers (1)

JotaBe
JotaBe

Reputation: 39015

The problem is that you are mixing two opposite designs: DDD and anemic model.

  • DDD: as far as the business logic there can be no dependencies, because the objects themselves are what must implement it
  • anemic model: this is the usual way to work with EF. The objects are POCOs: Fowler says "bags of properties setters and getters", and consider it an antipattern. All the logic is implemented in services that receive the entities, and change them according to business rules

If you use DDD

The classes in your application must be domain objects (entities and value objects). You must implement them without thinking how they will be stored in the database (or whatever backend you use). When you finish the domain object design you implement an EF model which satisfies the persistency needs of your domain objects. So, in many cases there will be not direct mapping between the domain objects (entities and value objects) and an EF entity.

I.e. in this implementation your domain object will have to store data at some point. And you'll have to implement an EF model that supports storing this data.

As to the dependencies, in this case they'll be in your domain objects, not in your EF entities. Then you can use the usual patterns (Factory, DI) to create your domain models. Probably one of this dependencies will be Repositories implemented with EF.

If you use anemic model

First I must say that there are many succesful implementations of this kind, even if Fowler says it's an anti-pattern. I'm not going to agree or disagree with Fowler, but I must expose the facts.

If you implement your application using an anemic model, you can start by designing your EF (anemic) model, and then implement all the business logic in service classes.

The big mistake

An anemic model is usually the result of a data-centric design. In the words of Fowler: I don't know why this anti-pattern is so common. I suspect it's due to many people who haven't really worked with a proper domain model, particularly if they come from a data background. So, if you start by doing this: At the core of my app are EF generated entities from Database First model. you'll have trouble to implement pure DDD (you can read this article to understand why)

Answering your comments:

1) this is an anemic model

2) you're expecting a direct mapping from stored data to domain objects. You receive an entity and want to add functionality to it. Nope! Your domain object has to use EF to request the persisted data, and not the other way round!

3) this is 1) again

You can find this article very interesting: The Anaemic Domain Model is no Anti-Pattern, it’s a SOLID design And its refutal: Rich Domain Is SOLID , Anaemic Domain Is An Anti Pattern

Upvotes: 8

Related Questions