Entity Framework Core: Stress-free data access
Matteo Migliore

Matteo Migliore is an entrepreneur and software architect with over 25 years of experience developing .NET-based solutions and evolving enterprise-grade application architectures.

He has led enterprise projects, trained hundreds of developers, and helped companies of all sizes simplify complexity by turning software into profit for their business.

Although ORMs have been around for at least a couple of decades now, the debate about whether to use them or not is still open: Entity Framework or NHibernate?

Or use Dapper? Or even directly ad hoc queries with ADO.NET? Stored procedures.

The two ways of looking at the matter arise from the fact that the DBA (Data Base Administrator, the designer of the database) was a predominant figure at the dawn of information technology and only later did that of the developer establish itself; the latter has often never been very comfortable with SQL code.

This is why the DBA in certain cases has become a developer, dealing with the SQL language, feeling more at ease with respect to using application code such as C#, C++ or other languages more suited to describing the application logic.

Consider that applications are on average made up of 90% of object-oriented code (OOP), and only the remaining part is dedicated to accessing the database.

If we consider all line of business applications, i.e. those that are the core business of companies, mainly we find applications that access and process data in the fastest possible way, which has become the main challenge of computing along with the ability to constantly add new features very quickly.

The need is to have highly performing applications and at the same time capable of evolving quickly to meet new market needs; in fact they are requests for new features from users and improvement of current ones within the software.

Our challenge as software designers is to create extremely fast applications that grow quickly and that they respect the requirements of users and not those of developers. In fact, developers often tend to over-engineer applications using solutions that are not needed or that do not offer great added value at that moment.

Learn how Entity Framework can help you manage data faster and more effectively with the Entity Framework course.

Developing in anticipation of subsequent needs is a serious mistake that many developers and teams make, because it does not respect the principle KISS, that is Keep It Simple and Stupid, keep things simple and stupid, where stupid means that they are very easy to understand and modify, avoiding pieces of code that are a tangle of conditions, ifs, monolithic classes and kilometric methods.

The less code you write the better the system

For the architecture and code to be the best it can be, they need to do the bare minimum.

Less is better than more, while obviously respecting the functional requirements, i.e. the application must do what it was designed for, but with minimal effort.

Want to write less code and get more done? Discover the right method in Entity Framework course.

Minimum expense with maximum yield, our job is to write as little code as possible to obtain the result.

Particularly complicated patterns, solutions that are difficult to maintain, solutions that require a lot of lines of code to implement, solutions that depend on complex configurations, or writing too much infrastructure code to be able to add a new feature or add a new endpoint, are all the archenemies of the developer and the team.

It would therefore be natural to think that between the two solutions, that is, between using ADO.NET to access data with direct queries, compared to using any ORM, the latter is the best solution to respect what I just said above: develop a simple and easy to maintain application.

Now that's the point, the SQL injected directly into the code .NET it is not at all an easy code to write and maintain.

In fact, within that code it is not possible to apply the intellisense features of Visual Studio which now allow us to automatically write a large part of the code and probably one of the greatest reasons for the success of using an IDE such as Visual Studio or Visual Studio Code.

Based on this reasoning I choose Entity Framework compared to other ORMs, because it is the official Microsoft solution and therefore developed, supported and maintained by Microsoft.

Compared to other frameworks which, although they are interesting and absolutely appreciable solutions because they are implemented by the community, have the risk of being abandoned or not quickly resolving developers' reports, precisely because they do not have a company behind them capable of offering a continuous service.

Entity Framework certainly offers advantages over using ADO.NET directly because it is possible to create the database mapping through classes that represent our application domain and which therefore allow us to write much faster by exploiting the power of LINQ.

P.S.
It's pronounced "linc", not "lincu", as I hear everyone say!

The power of LINQ comes from the fact that once we have described our application domain with our classes representing the DB tables, which are also modeled automatically

Relational model versus object model

The relational model is not very representative of reality, because it only reasons rectangles through tables and not in a hierarchical and set-theoretic way, as programming allows you to do OOP.

Object-oriented code allows us to represent the real world through classes, inheritance relationships, composition and polymorphism, fundamental principles that - if used correctly - they allow you to write much cleaner code.

This model representation transfer allows us to write code faster, because we are able to reason with more complex objects, writing methods that have logic within the set of properties.

Now we must make a very important distinction in the sense that theORM it is certainly very useful when reading the data but It gets more complicated when writing because saving a complex object graph requires a lot of mapping code.

Which, of course, is written (or generated) only once, but it must be written for each table for each new functionality that we want to write and for which we do not yet have the data structures.

It is necessary to do a lot of checking of the code we have written: in fact, persisting a graph can involve multiple tables and require checking objects that contain relationships with other objects, relationships with parents and tables that represent a hierarchy.

In short, a beautiful web of tables and reports.

This is precisely an example of incorrect design, with which the old management systems were "designed" and with which many management systems in Italy are still implemented: a lot of fields that transform a form into a Christmas tree, which the poor user is forced to fill out.

Often there is a very strict validation logic that requires him to enter all the data before being able to move within the application and therefore be able to save.

It forces him to waste a lot of time filling out the entire view, rather than having the possibility offered by modern applications, such as those developed in the United States in the last 15 years from which, however, the Italians have not understood and have not learned much since they persist in making monolithic applications, with a lot of fields.

This possibility of separating the different properties into small commands clearly allows us to have some much simpler and leaner code.

To solve this problem there are basically two ways:

  1. Only one database: using a ORM to read the data e ADO.NET to write them
  2. Separate storage: with CQRS split read storage from write storage

The single database solution

The first approach is the classic one, based on the use of a single database, but optimizing reading and writing performance by creating micro commands and micro readings.

The micro commands allow you to make small variations on the main aggregate using the "trick" of working on a maximum of 4-5 properties simultaneously involved in the business operation, rather than saving a whole complex graph at once.

The modification we make on the aggregate is not a modification that involves dozens and dozens of properties and above all it does not involve the entire graph, but typically only a small portion of the main object or one of its children.

I'll give you a simple example: if I have a customer who has a series of addresses, I won't need to show and save all the customer information, including other information such as VAT number, turnover and other customer-related information.

But then I have the possibility to save each field individually or a series of linked fields, such as adding addresses categorized by type.

So the saving code will be extremely simple and also extremely fast: because the locks I will have on the database will be much smaller, with a very limited number of tables and columns involved, with a great advantage for performance.

This explains why using an ORM to save data is not the most performant choice, precisely because we need to transfer data from an object to tables.

The solution with separate databases and CQRS

According to the pattern CQRS (Command Query Responsibility Segregation) normally the data reading part is completely separated from the writing part, both at the level of the machines that host the APIs also through a micro-services architecture, and at the storage level, where we could have a relational DB for reading the data and a document DB such as CosmosDB, for writing data.

If we use a document database like Cosmos DB we can think about documents. The document is a self-consistent entity that has a life of its own.

We can imagine it as if it were a Word document or a Photoshop image, where all the information we need is within the document itself.

There may be relationships with other documents, but basically the graph becomes a single document.

In this case the document database helps us because at that point the data will be saved by serializing it via JSON and therefore we will not need to map from the data to the database to the relational database tables, so persistence will be much easier and much faster, because ultimately it's about saving a file.

We won't have all the work of mapping the data.

When to use Entity Framework

Let's now come to the use of Entity Framework for the reading part. In the case of reading the data again the user interface must reflect simple, albeit complex, business logic.

Learn how to use Entity Framework as efficiently as possible with the Entity Framework course.

In the sense that the interface must show a small amount of data. You too know that showing the user 100 rows in a table is useless 99% of the time, because he is not able to read and compare them at the same time.

The most that an averagely gifted human being can do is work on 5 or 10 rows with a very small number of columns. So to improve performance you necessarily need to work on the design of the UI.

It is therefore mandatory to do optimization work by reducing the amount of data moving to and from remote systems from the API.

In this scenario we have data that is quite small, that contains few properties and that has one low data structuring.

Few data but good

Low data structuring means what user interface side I will have multiple changes of view to be able to go into detail and see the data in its entirety.

For example, if I have an invoice I will no longer have, as in the old ugly and difficult to use management systems, a single form that shows me all the invoice data, therefore the data relating to the customer and his tax data, the order lines, the payment data, etc.

Instead I have a split where each of this chunk of data is in a different view.

Using tabs or a wizard I have the header in one step, the order lines in another step, the summary in another step, the information relating to payments in yet another view.

At this point the data that I have to move to render them within the user interface or make them available to external services will be objects with few properties and low structuring.

The advantage is that of being able to have optimal performance, because subdivision of this type allows us to move a few hundred bytes at a time, being able to be very, very fast and make the most of the performance of cloud systems which always involve the use of the Internet.

Unlike on-premise systems that use the local network, the need to optimize both data transfer via HTTP and database queries allows us to create extremely efficient and also extremely scalable systems.

Leave your details in the form below

Matteo Migliore

Matteo Migliore is an entrepreneur and software architect with over 25 years of experience developing .NET-based solutions and evolving enterprise-grade application architectures.

Throughout his career, he has worked with organizations such as Cotonella, Il Sole 24 Ore, FIAT and NATO, leading teams in developing scalable platforms and modernizing complex legacy ecosystems.

He has trained hundreds of developers and supported companies of all sizes in turning software into a competitive advantage, reducing technical debt and achieving measurable business results.

Stai leggendo perché vuoi smettere di rattoppare software fragile.Scopri il metodo per progettare sistemi che reggono nel tempo.