Domain-Driven Design – Implement Service and Persistence or Just Persistence in DDD Infrastructure Layer

domain-driven-designentity-frameworkpersistenceservices

Short intro: I build an application, using .NET, Entity Framework (EF) as ORM and an SQL Server for persistence. My knowledge of SQL Server goes far beyond simple requests, and I use it to drastically cut on DB operations. Still I prefer to use EF to cut on writing direct SQL when possible.

I have an application service, f.e. IDogsService, which I would like to implement in the core. Implementation will have EF context (a repository) injected and should use the injected context for persistence. This is what I believe my architecture should be, according to DDD.

But I do everything differently. While IDogsService interface is in the core – implementation is in another project. And that implementation does not have any repository injected- it simply uses an internal db context, defined in the same project. The reason for such decision is simple: while core knows nothing about the repository, the IDogService's implementation may behave the way it wants, when it comes to persistance. And I believe the core should not care about repositories at all.

Pros of such approach: my db context is able to use all the benefits of SQL Server, therefore increasing performance. Cons: service's business logic is moved out of the core (I think it should stay in the core).

I have a strong feeling all of this is wrong and should be architected a little bit different. But do not know how. I really do not want to turn towards a repository pattern, since it will take away the benefits of SQL Server in favor of other RDBMS'es.

Any experience to share?

Best Answer

It sounds to me as though you are getting your self twisted around the dependency inversion principle.

I'd suggest giving Greg Young's 2009 essay on Generic Repositories a long read. The TL;DR is that in the common cases he prefers a contract with explicit definitions.

Udi Dahan, writing a few years earlier, had similar ideas.

But the basic plot is that the domain code describes its data needs as explicitly as it can via contract interfaces. The persistence components provide implementations that meet those contracts as efficiently as possible, and the composition roots wire everything together.

Cons: service's business logic is moved out of the core

I agree that would be a negative, but that shouldn't be happening -- unless you are trying to specify the implementation of the persistence solution in the business module.

Of course, I can revert to repository pattern, to become DB agnostic, but I will loose in performance

No no no; DB agnostic is OK -- it's (probably) the vague contracts that fail to give the implementations enough information get you into trouble.

Keep the concerns separate; but make the contract explicit enough that the implementations that recognize that a use case is a perfect fit for some feature can take advantage.

Often, this pattern looks like an interface that describes what is needed by the core domain, an optimized implementation that can do the job well, and a thin adapter in the middle that understands how to negotiate between the two.

Mark Seemann's blog also includes a good overview on dependencies.