I am creating a database that will keep track of my company's clients, and an app that will allow users inside the company to read/update/etc. the database. I'm using code-first EF Core to manage the database. The app is a C# .NET Blazor Server website, and the database is MySQL.
I initially decided to use a RESTful web API between the EF Core/database layer and the app layer, so it was roughly structured like this:
MyCo.WebApp -> MyCo.SDK -> (Server running MyCo.API) -> MyCo.Models -> (Server running MySQL DB)
MyCo.Modelscontains the data classes and the EF Core code (including the
DbContext) that interacts with the database,
MyCo.APIprovides the RESTful web API,
MyCo.SDKprovides an interface to call the API using an
HttpClient(from the .NET framework) and parses the JSON back into the data classes from
MyCo.Models(I'm referencing the data classes in that project so I didn't need to rewrite them), and
MyCo.WebAppis the user interface that displays the data and allows users to interact with it.
I initially thought having the API in the middle of everything was the right thing to do. We have other apps that will need to use this database, so having a single point of entry to the data would give us a way of controlling that. We also need to have an audit of all the changes that users make, and having the API layer gives us a single point where we can add a row to a Log table every time a user adds, updates or deletes an entity.
The problem came when I tried to retrieve the
Company property of a
Client must belong to a single
Company, but in the JSON that the API returned for a particular client, the
Company property was always null. This is because EF Core uses lazy loading as an optimization. Since I wasn't explicitly requesting the
Company property, EF Core had no reason to load it.
I could solve this by configuring EF Core to use eager loading, so all relations to an entity are loaded at the same time as the entity. But this comes at a performance cost, and there are times when I'd be happy to load a Contact entity without getting the associated Company with it.
This led me to realize that by introducing the Web API layer, I was actually losing a lot of the benefits of EF Core, like optimizing the DB calls using Linq. I could return the CompanyId inside the Contact and make another call to the API, but again I'm losing the benefit of being able to use EF Core to turn this into one DB call.
This answer to another question reasons that you shouldn't use the Repository pattern with Entity Framework because it itself is a Repository layer, which I think I agree with. The Web API I've built is essentially an additional Repository layer.
I'm now wondering if I need the API at all, since all apps that will use it in future will very likely be built in C#.NET, so they could use the EF Core
DbContext directly. So instead I would have this structure:
MyCo.WebApp -> MyCo.Models -> (Server running MySQL DB)
Alternatively I could add in a Service layer which would handle the calls to
DbContext, so the WebApp wouldn't need to know anything about how the database is structured.
MyCo.WebApp -> MyCo.Service -> MyCo.Models -> (Server running MySQL DB)
Or I could keep the API but change it to be non-RESTful, so it essentially acts as the Service layer - e.g. one endpoint to get a simple Contact data object, one endpoint to get a different Contact object which includes the Company data.
So my question is:
- Is there any value to having the RESTful Web API layer in my scenario?
- If not, should I use a Service layer, or is there some other common way of structuring applications of this type?