Christian Schou
  • Home
  • Blog
    • Programming
      • C#
      • PowerShell
      • Python
      • SQL
    • WordPress
      • Tutorials
    • Cloud
    • Home Automation
      • Home Assistant
        • Node-Red
    • Career
  • Services
  • Glossary
  • About
No Result
View All Result
Christian Schou
  • Home
  • Blog
    • Programming
      • C#
      • PowerShell
      • Python
      • SQL
    • WordPress
      • Tutorials
    • Cloud
    • Home Automation
      • Home Assistant
        • Node-Red
    • Career
  • Services
  • Glossary
  • About
No Result
View All Result
Christian Schou
No Result
View All Result
Home Programming C# EF Core
dynamically register entities

How to Dynamically Register Entities in DbContext by Extending ModelBuilder?

by Christian
23. Juli 2022
in EF Core
2

How can we make it easier for ourselves by implementing “dynamically register entities” functionality in our applications? One thing I often see, when helping others extend solutions or when I am asked to help optimize a project is that each and every entity in the solution is registered manually. It can turn your DbContext file into a quite big file if you got a lot of entities. To void this and help ourselves save some time (and lines), we can make an extension for ModelBuilder to dynamically register entities in DbContext.

By doing this we are sure that all entities in the future will get registered automatically when doing migrations and database updates. By the end of this guide, you will be able to extend ModelBuilder to automatically register your entities in the database using ModelBuilder.

Inhaltsverzeichnis
  1. What is ModelBuilder?
  2. What is a C# Entity?
  3. Dynamically Register Entities – But how?
    • Create an abstract class as base model
    • Create ModelBuilder extension to dynamically register entities
    • Register all entities in OnModelCreating
  4. Summary

What is ModelBuilder?

ModelBuilder is a class that lives in Microsoft.EntityFrameworkCore. It provides a simple API surface for configuring an IMutableModel that will help define the shape of your entities in an application. This includes relationships between the entities and how they are mapped to the database.

In C# we use ModelBuilder to construct a model for a context by overriding OnModelCreating (this is not a necessary thing in all projects) on your derived context.

What is a C# Entity?

When talking about C# an entity is a collection of fields and associated database operations. Entities in an application are fundamental to the application as they define data models. When they are added to DbContext they will be added as tables when you do a migration and update the database.

If you are ready, then let’s move on and write some code to make our lives easier when adding new models/entities to an application.

Dynamically Register Entities – But how?

In a traditional small project where we know that we won’t get a lot of entities, it makes fine sense just to register the entities manually in our DbContext class. We would just create a new DbSet for each of the models in our application, it would like something like what I have added below:

public class DatabaseContext : DbContext
{
    public DatabaseContext(DbContextOptions options) : base(options) 
    {
        <...>
    }

    public DbSet<Book> Books { get; set; }
    public DbSet<Author> Authors { get; set; }
    <...>
}

Create an abstract class as base model

This model is the one we instruct the ModelBuilder extension to include when it dynamically register entities during startup of the application.

Let’s create a new abstract class named BaseModel. I always put in the common properties for each model to avoid duplicate properties in my other models. The BaseModel I have created for this guide looks like the following below (it only contains an id), you can add or remove properties to this base class if you want to.

public abstract class BaseModel
{
   public GUID Id { get; set; }
}

When creating new models in your application, you can now simply inherit this abstract class named BaseModel. Let’s take a look at the Author model and see how it looks like:

public class Author : BaseModel
{
   public string? FirstName { get; set; }
   public string? LastName { get; set; }
   public string? Genre { get; set; }
   public GUID BookId { get; set; }
   public List<Book> Books { get; set; }
}

This will automatically make the Author have an ID of type GUID and it will automatically/dynamically be registered as an entity in our ModelBuilder in a moment.

Create ModelBuilder extension to dynamically register entities

To dynamically register entities, we have to make an extension to ModelBuilder and use Reflection to find all the models using BaseModel and add them to DbContext as an entity at runtime. Type represents type declarations (the reflection).

public static class ModelBuilderExtensions {
  public static void RegisterAllEntities<BaseModel>(this ModelBuilder modelBuilder, params Assembly[] assemblies) {
    IEnumerable<Type> types = assemblies.SelectMany(a => a.GetExportedTypes()).Where(c => c.IsClass && !c.IsAbstract && c.IsPublic &&
      typeof (BaseModel).IsAssignableFrom(c));
    foreach(Type type in types)
    modelBuilder.Entity(type);
  }
}

Okay, so what is happening in the code above?

  • We create an extension of ModelBuilder named RegisterAllEntities. It takes in the ModelBuilder and assemblies as parameters.
  • We then create an IEnumerable with Type and insert all models inheriting the abstract class named BaseModel.
  • We then add each model found in the assemblies as an entity.

Be careful how you use BaseModel now as it will include the model as an entity when doing migrations etc… some models are not meant for inclusion as an entity/table in the database. They are only in the application for moving data around.

Register all entities in OnModelCreating

Finally, we can now add our ModelBuilder extension to OnModelCreating in DbContext to dynamically register entities in the project at runtime. This is done in three lines as shown below:

protected override void OnModelCreating(ModelBuilder modelBuilder) {
  base.OnModelCreating(modelBuilder);
  var entitiesAssembly = typeof (BaseModel).Assembly;
  modelBuilder.RegisterAllEntities<BaseModel>(entitiesAssembly);
}

When you add a new migration now, the models inheriting the abstract class BaseModel will now be added as entities and also registered as entities during runtime.

Summary

This was a short guide (the first one in a long time). You are now able to dynamically register entities in your C# application in a nice, clean and easy way without having your DbContext file getting huge. At the same time you will be able to avoid duplicating properties/fields in your models.

I hope you learned something new or had your issue solved reading this article. If you got any questions, please let me know in the comments below. I will answer them as fast as possible. Until next time – Happy coding!

Tags: .NET 6.Net CoreASP.NET CoreC#CLIDevelopmentEFEF CoreEntity FrameworkEntity Framework Core
Previous Post

How to Compose an ASP.NET Core Web API (.NET 6) with an MS SQL Server 2022 on Linux in Docker

Next Post

How to build a RESTful Web API using ASP.NET Core and Entity Framework Core (.NET 6)

Christian

Christian

Hello 👋 My name is Christian and I am 26 years old. I'm an educated Software Developer with a primary focus on C#, .NET Core, Python, and PowerShell. Currently, I'm expanding my skills in Software Robots and Cloud Architecture. In some of my spare time, I share my knowledge about tech stuff on my blog.

Related Posts

No Content Available
Next Post
restful web api

How to build a RESTful Web API using ASP.NET Core and Entity Framework Core (.NET 6)

Comments 2

  1. Mir Mohamed Ullah says:
    3 Tagen ago

    This is very helpful and it reduces some daunting & boilerplate codes which might litter the DbContext class.

    But I am curious about its performance as you see that each time the dbcontext is initialized, it is doing the register entities operation – even if I want to get a single record from a single dbset. I am afraid if it would be an performance issue.

    Btw, many thanks for the hack 🙂

    Antworten
    • Christian says:
      2 Tagen ago

      Hi Mir Mohamed Ullah – thank you for your comment ✌️

      Exactly – you will get a much cleaner class for your database context! About performance – it should not be an issue as it’s typically only called once when the first instance of a derived context is created. The model is then cached for all further instances of the context in the app domain. You can disable the caching if you want to but I would not recommend it as that would seriously degrade performance.

      Oh and you are very welcome 😊

      Antworten

Schreibe einen Kommentar Antworten abbrechen

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert

Christian Schou

Christian Schou

Software Developer

Hello - my name is Christian and I am 26 years old. I'm an educated Software Developer with a primary focus on C#, .NET Core, Python, and PowerShell. Currently, I'm expanding my skills in Software Robots and Cloud Architecture. In some of my spare time, I share my knowledge about tech stuff on my blog.

Recent articles

personal website
Career

Top 6 things to add on your personal website to get hired for a tech job

by Christian
7. August 2022
0

Back in the days before the internet was a thing like it is today, we used to have business cards...

Read more
watchdog

The #1 guide to show real-time .NET 6 logs for Web Apps and APIs in a modern way using WatchDog for Free

13. August 2022
get hired for a tech job

5 tips to help you get hired for a tech job

31. Juli 2022
restful web api

How to build a RESTful Web API using ASP.NET Core and Entity Framework Core (.NET 6)

25. Juli 2022
dynamically register entities

How to Dynamically Register Entities in DbContext by Extending ModelBuilder?

23. Juli 2022

Christian Schou

Software Developer

Hello - my name is Christian and I am 26 years old. I'm an educated Software Developer with a primary focus on C#, .NET Core, Python, and PowerShell. Currently, I'm expanding my skills in Software Robots and Cloud Architecture. In some of my spare time, I share my knowledge about tech stuff on my blog.

Recent articles

personal website

Top 6 things to add on your personal website to get hired for a tech job

7. August 2022
watchdog

The #1 guide to show real-time .NET 6 logs for Web Apps and APIs in a modern way using WatchDog for Free

13. August 2022
get hired for a tech job

5 tips to help you get hired for a tech job

31. Juli 2022
  • de_DEDeutsch
    • da_DKDansk
    • en_USEnglish
    • hi_INहिन्दी
    • pt_BRPortuguês do Brasil
  • Contact
  • Datenschutzrichtlinie
  • Nutzungsbedingungen

© 2022 Christian Schou - All rights reserved.

No Result
View All Result
  • Home
  • Blog
    • Programming
      • C#
      • PowerShell
      • Python
      • SQL
    • WordPress
      • Tutorials
    • Cloud
    • Home Automation
      • Home Assistant
    • Career
  • Services
  • Glossary
  • About

© 2022 Christian Schou - All rights reserved.

I use cookies on my website to give you the most relevant experience by remembering your preferences and repeat visits. By clicking “Accept”, you consent to the use of ALL the cookies.
Do not sell my personal information.
Cookie settingsACCEPT
Privacy & Cookies Policy

Privacy Overview

This website uses cookies to improve your experience while you navigate through the website. Out of these cookies, the cookies that are categorized as necessary are stored on your browser as they are essential for the working of basic functionalities of the website. We also use third-party cookies that help us analyze and understand how you use this website. These cookies will be stored in your browser only with your consent. You also have the option to opt-out of these cookies. But opting out of some of these cookies may have an effect on your browsing experience.
Necessary
immer aktiv
Necessary cookies are absolutely essential for the website to function properly. This category only includes cookies that ensures basic functionalities and security features of the website. These cookies do not store any personal information.
Functional
Functional cookies help to perform certain functionalities like sharing the content of the website on social media platforms, collect feedbacks, and other third-party features.
Performance
Performance cookies are used to understand and analyze the key performance indexes of the website which helps in delivering a better user experience for the visitors.
Analytics
Analytical cookies are used to understand how visitors interact with the website. These cookies help provide information on metrics the number of visitors, bounce rate, traffic source, etc.
CookieDauerBeschreibung
__gads1 year 24 daysThe __gads cookie, set by Google, is stored under DoubleClick domain and tracks the number of times users see an advert, measures the success of the campaign and calculates its revenue. This cookie can only be read from the domain they are set on and will not track any data while browsing through other sites.
_ga2 yearsThe _ga cookie, installed by Google Analytics, calculates visitor, session and campaign data and also keeps track of site usage for the site's analytics report. The cookie stores information anonymously and assigns a randomly generated number to recognize unique visitors.
_ga_0J2F6JVWSD2 yearsThis cookie is installed by Google Analytics.
_gat_gtag_UA_84232734_11 minuteSet by Google to distinguish users.
_gid1 dayInstalled by Google Analytics, _gid cookie stores information on how visitors use a website, while also creating an analytics report of the website's performance. Some of the data that are collected include the number of visitors, their source, and the pages they visit anonymously.
YouTube2 yearsYouTube sets this cookie via embedded youtube-videos and registers anonymous statistical data. I embed YouTube videos in my articles/tutorials - you won't get the full experience of the articles if this is deactivated.
Advertisement
Advertisement cookies are used to provide visitors with relevant ads and marketing campaigns. These cookies track visitors across websites and collect information to provide customized ads.
CookieDauerBeschreibung
IDE1 year 24 daysGoogle DoubleClick IDE cookies are used to store information about how the user uses the website to present them with relevant ads and according to the user profile.
test_cookie15 minutesThe test_cookie is set by doubleclick.net and is used to determine if the user's browser supports cookies.
VISITOR_INFO1_LIVE5 months 27 daysA cookie set by YouTube to measure bandwidth that determines whether the user gets the new or old player interface.
YSCsessionYSC cookie is set by Youtube and is used to track the views of embedded videos on Youtube pages.
yt-remote-connected-devicesneverYouTube sets this cookie to store the video preferences of the user using embedded YouTube video.
yt-remote-device-idneverYouTube sets this cookie to store the video preferences of the user using embedded YouTube video.
Others
Other uncategorized cookies are those that are being analyzed and have not been classified into a category as yet.
SPEICHERN & AKZEPTIEREN
Unterstützt von CookieYes Logo