2

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?

  • You never gave us any reason as to why you are trying to make this so... complicated... And, why are you trying to avoid writing direct sql? Entityframework is a mess, why not just use dapper? – TheCatWhisperer May 23 '17 at 20:59
  • @TheCatWhisperer if you can make it simpler, I am glad to hear it. Maybe I will switch to dapper in the future, but the question is not about the ORM (I can easily write pure SQL, secured and fast). Question is about the whole architecture. What if I want to switch to Postgre? Queries will be different. Of course, I can revert to repository pattern, to become DB agnostic, but I will loose in performance. – Dima May 23 '17 at 21:13
  • This is the whole point of the repository pattern... if you want to change your underlying DB, you only have to make the change in code related to the DB. Also, EF is not persistence agnostic, it only supports a small subset of data storage technologies. EF has very very poor performance... – TheCatWhisperer May 23 '17 at 21:26
  • @TheCatWhisperer well, again, the scope of the question is wider. Although I doubt EF has poor performance when correctly used, many people simply misuse it. Anyway: the question is not about ORM, but about architecture. – Dima May 23 '17 at 21:32
  • 2
    @Dima Absolutely, separating persistence concerns away from business logic is a good thing; the problem is that LINQ-to-Entities queries are really just C#-friendly SQL statements - i.e. they are translated directly into SQL and executed in the RDBMS itself, not in your app's context. In other words, it might be best not to think of your LINQ-to-Entities queries as 'business logic' (at least as far as your application is concerned), but part of the Read/Write logic which you use to access your persistence. – Ben Cottrell May 23 '17 at 22:05
3

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.

  • Ahh, this is exactly the thing I needed to hear to achieve the paradigm shift: vague contracts that fail to give the implementations enough information get you into trouble. Somehow I have concentrated on a wrong level, thank you for the great answer! – Dima May 23 '17 at 22:34
1

I believe you're the business layer with data access layer. Having IDogService do business logic AND use a context to write db calls is a violation of SRP. It sounds like what you actually want is to separate the data access layer from the domain layer, but you can't really do that without abstracting them ... ergo the repository pattern.

Make IDogService implementation (DogService) do business logic only, and make it depend on a IDogRepository. Keep those 3 classes in the Core, while having DogRepository on the different project. You solve 2 issues: 1 SRP violation, and now you can easily switch to Posgress w/o having to violate the Open/Closed principle too on DogService when you do that.

  • Had to google "SPR" before it hit my mind that you probably mean SRP :) – Dima May 23 '17 at 22:10
  • Exactly, I have been trying to avoid abstracting data access to keep the performance benefits I have. – Dima May 23 '17 at 22:15

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.