1

I'm trying to build a project using onion architecture (just a "Northwind"ish type app to get more up to speed with .NET Core). I also want to get a better grasp on Onion Architecture principals. I understand it's not a one-size fits all solution, but I want to try to utilize most of the principals in this sample app.

I'm using EF Core and generating my data layer with the dotnet ef dbcontext scaffold command. My thought is, I will maintain the database (via a VS Database project) and regenerate these files each time - so they wouldn't be touched by hand ever. It seems that most of these entities could also act as domain entities.

My project structure would look something like this:

  • Eastwind.sln
    • Core
      • Eastwind.Domain
        • Interfaces\
        • Entities\ - (location of generated POCO entities from EF)
        • Extensions\
    • Outer
      • Eastwind.Data - (location of dbcontext & EF config associating entities to datastore)
      • Eastwind.Services
      • Eastwind.WebApi
    • Client (WebApi clients)
      • Eastwind.Client.Web
      • Eastwind.Client.Wpf

My questions are:

  • Does it make sense to generate the entities (POCO classes) in the core/domain layer and keep the EF Configuration (fluent config code) and DbContext in a separate data layer that's outside of the Core?
  • Does someone know of a good sample project that really utilizes the onion principals well? I've seen a few and they're questionable at best.
  • Any other notes (or critiques) on issues in my structure relating to onion?

My thought is the data layer should sit outside the core still and rely on the entities on the lower layers (core). This seems onion'y to me still, but I haven't really seen anyone structure a project this way.

EDIT:

The Client projects are arguably insignificant to this question, as they will not utilize any of these libraries directly.

I am going to transform any input or output from the API to DTOs in order to keep them specific to the calls - combining and/or simplifying the data to keep them light weight and prevent the need for multiple round-trips as much as possible.

I MIGHT put the DTOs in a separate library to at least share those objects with the WPF Client project, but the Web Client project is using Angular so they will need to be redefined there.

1

POCO's in the Domain

Really this is one half dozen the other.

  • If your domain generates these objects, then great you are sharing their implementation for everyone else to use.

  • If many clients use these to submit data, then also great you have shared the implementation. Although you could have similarly achieved this by placing them in a third shared library.

  • It increases the surface of the public interface, and means that you are now locked into providing these always. This is not so great as it is a source of unintended complexity. Some clients will benefit, others are lumped with baggage.

I would only provide access to those Objects generated by the Domain logic itself. The others while useful should be housed in their own separate binary.

Domain Entities

Take this opportunity to make your POCOs provide strong constructors, and enforce mutation rules.

This will help to ensure that the Domain Entities are correctly constructed and manipulated.

  • On the pro side all clients can now be sure that they are constructing the data correctly. Even better if you offer construction based validation.

  • On the con side, these classes are not one size fits all. There will be clients who need to implement their own variant. They can achieve this via the exposed interfaces, but are still saddled with classes they do not use.

Of course you could provide various implementations of these objects to enhance the good outcomes, while avoiding the bad. The only difference are the extra libraries.

  • Thank you for your answer. I should have mentioned that in the API project I am planning to transform these into DTO's and thus allowing me to combine multiple objects and keeping them as simple as possible to prevent multiple round-trip calls from the clients. Really the Client projects probably shouldn't have been even included in my project layout because they will not utilize these other projects in any way. Putting the DTOs in a shared lib that is utilized by Wpf and the API would prevent a little duplication, but I'm using Angular for the web so I will need to reimplement there still – Adam Plocher Apr 10 at 21:53
  • 1
    @Kain0_0 POCO's have strong constructors and are often immutable. You're confusing them with brainless behavior free DTO's that follow the Java Bean convention of wrapping fields in getters and setters. A POCO or POJO is just a plain old object free of weird inheritance, enterprisy framework, or annotation requirements. – candied_orange Apr 12 at 5:09
  • @candied_orange Weird inheritance? Not sure I follow, I see no reason why a POCO should not implement domain concepts. I do agree that they should not inherit from third-party interfaces/classes. Fair enough about terminology, I translated POCO to POD (Plain Old Data) - my bad. Still many people think that a class definition must make Objects (in the sense of OO), which isn't true and isn't helped by Java forcing everything to inherit from Object. – Kain0_0 Apr 12 at 7:54

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.