In this new post, I want to give a complete example of minimal APIs in Blazor with Entity Framework Core with complex objects. I always struggle to have a solution working when my model has dependencies with other object. Here I show my test and my code. The code is in NET9. In the Microsoft documentation, there are some examples but it is not complex enough. A few days ago, I posted about another problem I had with NET9 and Entity Framework Core.
The full source code of this post is available on GitHub. If you have any questions, please comment below or post in the forum.
The complete code is spanned through those posts:
- APIs with Entity Framework Core
- APIs with Entity Framework Core: POST
- APIs with Entity Framework Core: PUT
Scenario
Very often in my projects, I want to save the data in the database. I always use the models I created in the Domain
project. This is because I like to have a clear code as I explained in my earlier post. Let me clear my common problem.
Joined tables
So, let me show a real database I’m working on. As you can see I have a few tables but not all of them are coming strictly from the code. The tables Clients
, ClientAddresses
and tbl_Channels
are created from the Domain
. ChannelClient
is a joined table that Entity Framework Core is creating automatically.

To avoid distractions, I only show the code necessary to create the tables with minimal data. So, I can focus only on the implementation of the code to insert or update in the database the data. Once the logic is clear, it is easy to extend it to other fields.
Tables explanation
Now, the implementation has 4 tables. As I said, 3 are generated from the code. One is generated from Entity Framework Core as a joined table. Why? Here is an example. In your form, you have a dropdown list with multiple choices. By the way, in this example, I use my AutoComplete component for Blazor.

The list is from the tbl_Channel
s table. Because the user can choose more than one option, the database has to save all of them. That means, for a client I have to save one or more records. This is a N:M
relation. There are several Clients
per Channel
and the same Client has several Channels. For example: Channel 1 has Channels 1,2,5, Client 1 has Channels 1,2

Domain implementation
As I mentioned before, the model to create the database lies in the Domain
layer. So, I created a new project for it.
Channel
This table contains the items to display in the dropdown list. The user can select one or more of them. The implementation is quite simple.
[Table("tbl_Channels")]
public class Channel
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
[JsonPropertyName("Id")]
public long Id { get; set; }
[Required]
[JsonPropertyName("name")]
public string? Name { get; set; }
[JsonIgnore]
public ICollection<Client>? Client { get; set; }
}
Table
attribute defines the name of the table in the database. Key
attributes defined this field as a key and it is generated automatically by the database. JsonPropertyName
defines the name of the fields when the application reads or returns this object via API. JsonIgnore
attribute means that this field won’t be added in the json
. I added this attribute to avoid recursion when the json
will be created.
Now, I want to link this table with the Client
table. For that, I added an ICollection
of Client
that is the model I’m going to create now.
Clients
This table contains the list of clients. Also, here I have to define the link with the Channel table.
Now, I continue with the explanation of how to use APIs with Entity Framework Core and later I will add the ClientAddress
table.
Persistence and migrations
Now, because I want to create this project as a future reference, I am going to create a Persistence layer. Generally speaking, this is where I will create the implementation for the repositories and the context. Also, in this project, I will add the migration using Entity Framework Core.
To give you more info, I recorded a video how I create the Persistence project. Also, you see how I generate the migration using Entity Framework Code. In this project, I will add the context for the database and the service registration for this layer (and the context). The project is called APIEFCore.Persistence
.
Create MyDbContext
First, I have to add the creation of the database context. For that, I created a file called MyDbContext
and the content is the following
public class MyDbContext : DbContext
{
public MyDbContext(DbContextOptions<MyDbContext> option) : base(option)
{
}
public DbSet<Client> Clients { get; set; }
public DbSet<Channel> Channels { get; set; }
}
Whit this code, I tell the Entity Framework Core that the context contains 2 tables. Those tables can be used with the names Clients
and Channels
.
Registration service
Now, because I want to use this project as a reference, I also created a persistence service registration to register the context and other services in the IServiceCollection
. The code is the following
public static class PersistenceServiceRegistration
{
public const string ConnectionName = "DefaultConnection";
public static IServiceCollection AddPersistenceServices(this IServiceCollection services,
IConfiguration configuration,
string cnnStringName = ConnectionName,
string? cnnString = null)
{
if (cnnString == null)
cnnString = configuration.GetConnectionString(cnnStringName);
services.AddDbContext<MyDbContext>(options => options.UseSqlServer(cnnString));
return services;
}
}
In order to register this code, I have to add in the server project in the builder
this service using this line:
builder.Services.AddPersistenceServices(builder.Configuration);
After that, I can use the database and the context in the application.
Create migration
Now, I have to generate the code to create the database. For that, I use what Entity Framework offers. I open the Package Manager Console and here I start to add the migration for the context. Because the solution I created is based on Blazor with Individual Authentication, in the project there are 2 contexts. I created MyDbContex
t but for the project I have the ApplicationDbContext
. So, I have to specified what context I want to use. In the app.settings.json
I can see the connection string for the database that is for a MSSQLLocalDb.
So, to generate the initial migration for my context, in the Package Manager Console, I have to run the following command
add-migration InitialMigration -Context MyDbContext
With that, Entity Framework generates the migration for this context.
Update database
Now that the migration is created, I can update the structure of the database. As I said, I have 2 contexts and for that I have to run twice the update.
Starting with the ApplicationDbContext
, in the Package Manager Console, I am going to run the following command
update-database -Context ApplicationDbContext
This is creating the tables for the ASPNET Users and Roles tables that I discussed a lot in my earlier posts. Remember to specify the context. Now, I can run a similar command for my context
update-database -Context MyDbContext
The result of all of it is the creation of the tables as shown in the following screenshot.

In the video, I show the structure of the tables that is what you see at the top of this post.
Minimal APIs creation
The next step is to create the minimal APIs based on the models I created in the Domain
layer. Also, for this step I created a video. To generate the APIs, I am going to use Visual Studio and in particular the Scaffolded Item.

Now, with this tool, I can generate an API based on my model and Entity Framework. So, select the option API with read/write endpoints, using Entity Framework.

Then, I have to choose the following fields:
- Model class: one of the models in the
Domain
layer - Endpoints class: I like to create a new file for each model
- DbContext: that in this case is MyDbContext
After that, I want to use OpenAPI and TypedResults as checked by default.

After the first endpoint for Client
is created, I want to add another one for Channel
. I can’t execute the procedure again because it returns an error. For that, go to the Program.cs
in the server project and commend
app.MapClientEndpoints();
After that, I can generate a new API using the New Scaffolded Item option. I’m not sure if it is possible to avoid this error in some way. If you comment this line, it is working.
Swagger
Now, Swagger is added automatically to the project. So, I can play with it. If you use my project, the link is
https://localhost:7191/swagger/index.html
If I try to create a new Channel
, it is working and I can see that APIs with Entity Framework Core are there. But this is only the beginning.

Wrap up
In conclusion, in this first post of APIs with Entity Framework Core, I show you how to set the basis of the project and how:
- to create the APIs using the Scaffolded tool
- the create the database.
The difficult part is coming! I have to start to change the code to add the channels to the client. Also, I want to update this record. How can I do it? Soon the next post.
Happy coding!