5

I am building a new ASP.NET Core 5 MVC app. I want to use clean architecture as outlined in Microsoft's web app architecture ebook.

I am also studying eShopOnWeb sample application available here :

https://github.com/dotnet-architecture/eShopOnWeb

What I understand from the ebook and sample app is - EF Core entity classes (say Customer, Product, Order) will go inside ApplicationCore project's Entities folder. The DbContext will be in Infrastructure project.

My confusion is: is it alright to add data annotation schema attributes such as [Table], [DatabaseGenerated], and [Key] on these entity classes inside ApplicationCore project? If not, where should I add these data annotations?

Any advice in this regards is highly appreciated.

Thank you.

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
Web Dev
  • 675
  • 1
  • 8
  • 15
  • 6
    You can use [fluent API](https://learn.microsoft.com/en-us/ef/core/modeling/#use-fluent-api-to-configure-a-model) to configure the model - that will allow you to remove attributes and have configuration in Infrastructure project. – Guru Stron Apr 02 '21 at 06:37
  • To add to that, you can get away with a lot of the configuration based on convention. If you find you're having to add the same configuration over and over again, you're likely trying to fight EF Core. Try to avoid this unless you have good reason or see if there is a way to override the default behaviour. – Lolop Apr 02 '21 at 06:41
  • What you ask has little to do with architecture. In fact, in most cases you *wouldn't* be using the same DTOs for data access (ie with EF Core), business logic or API/ViewModel DTOs. The entities loaded by EF Core would belong to whatever project or layer you put data-access code. Which doesn't have to be called `Infrastructure`. In most cases you'd have to map the database DTOs to business DTOs then to API DTOs – Panagiotis Kanavos Apr 02 '21 at 06:43
  • So adding data attributes to the data DTOs isn't a problem. You can use fluent configuration instead of course, especially when you don't want separate Business/Data DTOs. Fluent configuration means you have all the config in one place, in the DbContext, which could make maintenance/versioning easier – Panagiotis Kanavos Apr 02 '21 at 06:48
  • Although a valid question, I think the answer to this question will always be opinionated. Anyhow, I liked [this presentation on clean architecture](https://www.youtube.com/watch?v=dK4Yb6-LxAk). It also suggests to use the EF fluent API, because (according to the presenter) it's more powerful. I'm not fully sure on this myself. – JHBonarius Apr 02 '21 at 06:52
  • PS: `Clean Architecture` isn't a specific architectural design, it's just a brand name created by a specific non-Microsoft author. Talking about capitalized `Clean Architecture` is like asking for `EF Core entity classes and Colgate` or `EF Core entity classes and Heavy Metal`. Yes, you should structure your project in a way that's clean, easily understandable, prevents changes from leaking all over the place. But that doesn't mean you need a specific set of projects, or even multiple projects. You need to think what's needed for *your* projects, *your* specific problems – Panagiotis Kanavos Apr 02 '21 at 06:53
  • @PanagiotisKanavos haha, did you just refer to Uncle Bob as "a specific non-Microsoft author"? He deserves more than that ;) – JHBonarius Apr 02 '21 at 06:56
  • @JHBonarius then you know why, and seriously, in this subject, not really. This is neither gospel or even original. That book combines ideas and designs that have been around for 20 years, already described in a *lot* of books, articles and magazines like the 1990s-2000s era Dr Dobbs, Software Development Magazine, Journal of Object-Oriented Programming, Microsoft Systems Journal/MSDN Magazine. And some of the ideas like "generic repositories" are just plain bad ideas when used on top of ORMs. The real take away is *think for yourself* – Panagiotis Kanavos Apr 02 '21 at 07:08
  • @WebDev this isn't just opinion-based, it depends on the specific application type. I have a reporting application, which means I have little business logic and lots of *display* logic. This means that for many classes the database is built first and the classes have to match the *query results*. So there's little need for attributes on properties, lots of mapping to views instead of tables (typically convention-based). On the other hand, I need a *LOT* of `Display` attributes to avoid hand-coding every grid and filter. – Panagiotis Kanavos Apr 02 '21 at 07:09
  • @WebDev but even in this case, the design for an intranet reporting portal where the data is known and changes relatively infrequently is different from a reporting component or library that has to handle every possible class and shape. For me, it makes sense to *NOT* overgeneralize, because it makes things harder to write and maintain (I've learned that the hard-way). Putting a `Display` attribute on a class is OK. A report library author though can't do that, so there must be a different way to specify constraints, display through code or even configuration – Panagiotis Kanavos Apr 02 '21 at 07:15
  • @PanagiotisKanavos having worked in large teams, I prefer that not everybody "think for themselves", but having a general system architect that sets the way of working. And you can learn from the best practices of others. Heck, most work is based on the work of others. Remember Isaac Newton (1675)? His quote: _"If I have seen further it is by standing on the shoulders of Giants."_ – JHBonarius Apr 02 '21 at 07:49
  • Thank you all for your insight and help. – Web Dev Apr 02 '21 at 21:44

1 Answers1

2

In the example of eShopOnWeb they separate Entities and configuration models. So, that means to have clean architecture you don't need annotations directly in these Entities.

You can use FluentAPI, as they used as well in the Infrastructure/Data/Config directory.

So, if you have a separate project for DataContext that is the best location for describing your entities with FluentAPI in this case.

More information about FluentAPI: https://learn.microsoft.com/en-us/ef/ef6/modeling/code-first/fluent/types-and-properties

Emin Mesic
  • 1,681
  • 2
  • 8
  • 18