Boost Your EF Core Productivity in PostgreSQL With Entity Developer



This content originally appeared on DEV Community and was authored by Anton Martyniuk

EF Core has been my go-to ORM for many years because it significantly improves developer productivity.
However, managing data models using traditional approaches like Database-First or Code-First can become boring and time-consuming, especially as your projects grow.

While Database-First allows rapid model generation from existing databases, and Code-First provides flexible schema migrations, both approaches can slow down development when manually configuring complex entities and relationships.

Luckily, there is a more efficient and modern way: the Model-First approach.
Instead of hand-writing your models and configurations, you design them visually.
These visual models are then automatically transformed into EF Core entities and database schemas.

One of the best tools for implementing the Model-First approach is Entity Developer by Devart.

It features an intuitive drag-and-drop interface that lets you easily visualize and manage your data models, significantly reducing manual coding and errors.

Today, I will show you how to rapidly design, generate, and synchronize your EF Core models for PostgreSQL databases using Entity Developer.
You’ll discover how this powerful tool can simplify your workflow, improve code quality, and boost your overall development efficiency.

In this post, we will explore:

  • Getting Started: Creating Your EF Core Model for PostgreSQL
  • Designing Your Data Model Visually
  • Generating PostgreSQL Database Scripts
  • Automating EF Core Code Generation
  • Core Benefits for EF Core and PostgreSQL Development

Let’s dive in!

P.S.: I publish all these blogs on my own website: Read original post here
Subscribe to my newsletter to improve your .NET skills.
Download the source code for this newsletter for free.

Getting Started: Creating Your EF Core Model for PostgreSQL

Entity Developer is an easy-to-use visual tool designed to simplify working with EF Core.
It allows developers to quickly create and visualize data models using a simple drag-and-drop interface.

You don’t need to write much code, making it perfect for those who prefer visual tools over manual coding.
This tool is useful for developers of all levels: from juniors to seniors.

Entity Developer supports two main approaches: Model-First and Database-First.

Entity Developer supports the following databases:

  • PostgreSQL
  • MySQL
  • Oracle
  • MariaDB
  • SQLite

Today, we’ll focus on using Entity Developer with EF Core and PostgreSQL, specifically with the Model-First approach.

Screenshot_5

Let’s set up our first EF Core model with Entity Developer.

Follow these simple steps:

Step 1: Install Entity Developer

First, download and install Entity Developer from its official website.

Screenshot_1

Once installed, you can run Entity Developer as a standalone tool or use it inside Visual Studio.
For this guide, we’ll use the standalone version.

Step 2: Start the Create Model Wizard

Open Entity Developer, click “File → New Model,” and the Create Model Wizard will open.
Select “EF Core Model,” then give your Model a clear, descriptive name:

Screenshot_2

Step 3: Configure Entity Model

Choose the Model-First approach.
This lets you visually design your database model first, then automatically generate the necessary code and database schema.

Screenshot_3

You will need to install dotConnect for PostgreSQL to connect EF Core with a PostgreSQL database.
It comes with Visual Studio integration and installs the required DLLs for a database communication provider.

Next, configure the following settings:

  • Check “Use the connection string from appsettings.json”
  • Enter the connection string name as “Postgres.”
  • Set the DbContext name to “ShipmentDbContext.”
  • Select your EF Core version (EF 9 is supported).

Screenshot_4

Your initial setup is complete! Now, let’s start designing our entity models.

Designing Your Data Model Visually

Let’s design a real-world application with three entities: Order, Shipment, and Product.
Each Order has one Shipment and multiple Products.

Follow these simple steps:

Step 1: Create an Entity Class

Right-click anywhere on the diagram and select “Add → New Class”.

Create 3 entities: Order, Shipment and Product.

Step 2: Add Properties to the Entities

To add properties, right-click the entity and select “Edit” or press “Enter”.
In the opened dialog, add all the properties.

Screenshot_6

Add the following properties to the entities:

Order:

  • Id (Primary key, UUID)
  • Number (string)
  • Date (DateTime)
  • CustomerName (String)
  • CustomerEmail (String)
  • Status (String)

Shipment:

  • Id (Primary key, UUID)
  • TrackingNumber (string)
  • Carrier (string)
  • Address (string)
  • ShippedDate (DateTime, nullable)
  • DeliveredDate (DateTime, nullable)
  • Price (decimal)
  • ShipmentId (UUID)

Product:

  • Id (Primary key, UUID)
  • Name (string)
  • Description (DateTime)
  • Price (Int32)
  • Quantity (Int32)
  • OrderId (UUID)

The visual schema should look like this:

Screenshot_7

Step 3: Add Relations between Entities

Next, define the relationships between entities:

  • Shipment has a one-to-one relationship with Order.
  • Order has a one-to-many relationship with Product.

To create a relationship, right-click on the Shipment entity and select “Add → New Association” from the context menu.

Screenshot_8

In the dialog, select the following:

  1. Order Entity (Shipment has OrderId)
  2. Set Cardinality to OneToOne.
  3. Choose None for On Delete Action.
  4. Map Shipment (OrderId) to Order (Id).

Repeat this process to create a OneToMany relationship between Order and Product.

Your completed schema will look like this:

Screenshot_9

Entity Developer also supports inheritance hierarchies using the “New Inheritance” context action.
This is useful for EF Core patterns like Table-Per-Hierarchy (TPH) and Table-Per-Type (TPT).

Using Entity Developer makes entity modeling simple and enjoyable.
With its intuitive drag-and-drop interface, you won’t need to write classes or handle relationships manually.

Next, we’ll explore how Entity Developer automates PostgreSQL database script creation.

Generating PostgreSQL Database Scripts

Entity Developer makes generating PostgreSQL database scripts simple.
It automatically creates SQL scripts based on your visual EF Core model, helping you quickly set up or update your database.

To generate a script, follow these simple steps:

In Entity Developer, click “Model → Generate Database Script From Model” from the main menu:

Screenshot_10

In the dialog that opens, configure the following settings:

  • Target Server: PostgreSQL
  • Server Version: 17
  • Target schema: shipments (our database schema)
  • Data Provider: Devart.Data.PostgreSql

Screenshot_11

Entity Developer will display a preview of the script before making any changes.
This lets you check the database updates carefully.

As a result, Entity Developer will create the following database schema:

CREATE TABLE shipments."Orders" (
   "Id" UUID NOT NULL,
   "Number" VARCHAR NOT NULL,
   "Date" TIMESTAMP NOT NULL,
   "CustomerName" VARCHAR NOT NULL,
   "CustomerEmail" VARCHAR NOT NULL,
   "Status" VARCHAR NOT NULL,
   CONSTRAINT "PK_Orders" PRIMARY KEY ("Id")
);

CREATE TABLE shipments."Products" (
   "Id" UUID NOT NULL,
   "Name" VARCHAR NOT NULL,
   "Description" VARCHAR NOT NULL,
   "Price" DECIMAL NOT NULL,
   "Quantity" INT4 NOT NULL,
   "OrderId" UUID NOT NULL,
   CONSTRAINT "PK_Products" PRIMARY KEY ("Id"),
   CONSTRAINT "FK_Products_Orders_0" FOREIGN KEY ("OrderId") REFERENCES shipments."Orders" ("Id") ON DELETE NO ACTION
);

CREATE TABLE shipments."Shipments" (
   "Id" UUID NOT NULL,
   "TrackingNumber" VARCHAR NOT NULL,
   "Carrier" VARCHAR NOT NULL,
   "Address" VARCHAR NOT NULL,
   "ShippedDate" TIMESTAMP,
   "DeliveredDate" TIMESTAMP NOT NULL,
   "Price" DECIMAL NOT NULL,
   "OrderId" UUID NOT NULL,
   CONSTRAINT "PK_Shipments" PRIMARY KEY ("Id"),
   CONSTRAINT "FK_Shipments_Orders_0" FOREIGN KEY ("OrderId") REFERENCES shipments."Orders" ("Id") ON DELETE NO ACTION
);

You can use this SQL script to create all the needed database tables in your PostgreSQL.

Alternatively, you have two options for applying your database updates:

  • Update database directly from the Entity Developer (from the context menu in the Designer).
  • Use EF Core to generate migrations.

Now let’s explore how to generate code with Entity Developer for EF Core.

Automating EF Core Code Generation

With Entity Developer, turning your visual database model into code is easy.
Let’s quickly set up an EF Core Web API project using Visual Studio.

First, install these necessary NuGet packages:

dotnet add package Microsoft.EntityFrameworkCore
dotnet add package Microsoft.EntityFrameworkCore.Tools
dotnet add package Devart.Data.PostgreSql.EFCore

We’ll use Devart.Data.PostgreSql.EFCore as our PostgreSQL provider for EF Core.

Next, convert your Entity Developer model to code:

  1. Ensure your Entity Developer project is saved.
  2. Click “Model → Generate code” from the main menu

Screenshot_12

Entity Developer uses T4 templates to generate C# entity classes, DbContext, and mapping configurations automatically.
Copy these files into your Visual Studio solution.

Entity Developer has created Order, Product and Shipment entities.
Here is what they look like in the code:

public partial class Order
{
    public Order()
    {
        this.Products = new List<Product>();
        OnCreated();
    }

    public Guid Id { get; set; }
    public string Number { get; set; }
    public DateTime Date { get; set; }
    public string CustomerName { get; set; }
    public string CustomerEmail { get; set; }
    public string Status { get; set; }
    public Guid ShipmentId { get; set; }

    public virtual Shipment Shipment { get; set; }
    public virtual IList<Product> Products { get; set; }

    partial void OnCreated();
}
public partial class Product
{
    public Product()
    {
        OnCreated();
    }

    public Guid Id { get; set; }
    public string Name { get; set; }
    public string Description { get; set; }
    public decimal Price { get; set; }
    public int Quantity { get; set; }
    public Guid OrderId { get; set; }

    public virtual Order Order { get; set; }

    partial void OnCreated();
}
public partial class Shipment
{
    public Shipment()
    {
        OnCreated();
    }

    public Guid Id { get; set; }
    public string TrackingNumber { get; set; }
    public string Carrier { get; set; }
    public string Address { get; set; }
    public DateTime? ShippedDate { get; set; }
    public DateTime DeliveredDate { get; set; }
    public decimal Price { get; set; }

    public virtual Order Order { get; set; }

    partial void OnCreated();
}

And here is what our ShipmentDbContext looks like:

public partial class ShipmentDbContext : DbContext
{
    public ShipmentDbContext(DbContextOptions<ShipmentDbContext> options) :
        base(options)
    {
        OnCreated();
    }

    public virtual DbSet<Order> Orders { get; set; }
    public virtual DbSet<Shipment> Shipments { get; set; }
    public virtual DbSet<Product> Products { get; set; }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);

        this.OrderMapping(modelBuilder);
        this.CustomizeOrderMapping(modelBuilder);

        this.ShipmentMapping(modelBuilder);
        this.CustomizeShipmentMapping(modelBuilder);

        this.ProductMapping(modelBuilder);
        this.CustomizeProductMapping(modelBuilder);

        RelationshipsMapping(modelBuilder);
        CustomizeMapping(ref modelBuilder);
    }

    private void OrderMapping(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Order>().ToTable(@"Orders");
       modelBuilder.Entity<Order>().Property(x => x.Id).HasColumnName(@"Id").IsRequired().ValueGeneratedNever();
       modelBuilder.Entity<Order>().Property(x => x.Number).HasColumnName(@"Number").IsRequired().ValueGeneratedNever();
       modelBuilder.Entity<Order>().Property(x => x.Date).HasColumnName(@"Date").IsRequired().ValueGeneratedNever();
       modelBuilder.Entity<Order>().Property(x => x.CustomerName).HasColumnName(@"CustomerName").IsRequired().ValueGeneratedNever();
       modelBuilder.Entity<Order>().Property(x => x.CustomerEmail).HasColumnName(@"CustomerEmail").IsRequired().ValueGeneratedNever();
       modelBuilder.Entity<Order>().Property(x => x.Status).HasColumnName(@"Status").IsRequired().ValueGeneratedNever();
       modelBuilder.Entity<Order>().HasKey(@"Id");
    }

    private void ShipmentMapping(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Shipment>().ToTable(@"Shipments");
       modelBuilder.Entity<Shipment>().Property(x => x.Id).HasColumnName(@"Id").IsRequired().ValueGeneratedNever();
       modelBuilder.Entity<Shipment>().Property(x => x.TrackingNumber).HasColumnName(@"TrackingNumber").IsRequired().ValueGeneratedNever();
       modelBuilder.Entity<Shipment>().Property(x => x.Carrier).HasColumnName(@"Carrier").IsRequired().ValueGeneratedNever();
       modelBuilder.Entity<Shipment>().Property(x => x.Address).HasColumnName(@"Address").IsRequired().ValueGeneratedNever();
       modelBuilder.Entity<Shipment>().Property(x => x.ShippedDate).HasColumnName(@"ShippedDate").ValueGeneratedNever();
       modelBuilder.Entity<Shipment>().Property(x => x.DeliveredDate).HasColumnName(@"DeliveredDate").IsRequired().ValueGeneratedNever();
       modelBuilder.Entity<Shipment>().Property(x => x.Price).HasColumnName(@"Price").IsRequired().ValueGeneratedNever();
       modelBuilder.Entity<Shipment>().Property(x => x.OrderId).HasColumnName(@"OrderId").IsRequired().ValueGeneratedNever();
       modelBuilder.Entity<Shipment>().HasKey(@"Id");
    }

    private void ProductMapping(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Product>().ToTable(@"Products");
       modelBuilder.Entity<Product>().Property(x => x.Id).HasColumnName(@"Id").IsRequired().ValueGeneratedNever();
       modelBuilder.Entity<Product>().Property(x => x.Name).HasColumnName(@"Name").IsRequired().ValueGeneratedNever();
       modelBuilder.Entity<Product>().Property(x => x.Description).HasColumnName(@"Description").IsRequired().ValueGeneratedNever();
       modelBuilder.Entity<Product>().Property(x => x.Price).HasColumnName(@"Price").IsRequired().ValueGeneratedNever();
       modelBuilder.Entity<Product>().Property(x => x.Quantity).HasColumnName(@"Quantity").IsRequired().ValueGeneratedNever();
       modelBuilder.Entity<Product>().Property(x => x.OrderId).HasColumnName(@"OrderId").IsRequired().ValueGeneratedNever();
       modelBuilder.Entity<Product>().HasKey(@"Id");
    }

    private void RelationshipsMapping(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Order>()
          .HasOne(x => x.Shipment)
          .WithOne(op => op.Order)
          .HasForeignKey(typeof(Shipment), @"OrderId")
          .IsRequired(false);

       modelBuilder.Entity<Order>()
          .HasMany(x => x.Products)
          .WithOne(op => op.Order)
          .HasForeignKey(@"OrderId")
          .IsRequired(true);

       modelBuilder.Entity<Product>()
          .HasOne(x => x.Order)
          .WithMany(op => op.Products)
          .HasForeignKey(@"OrderId")
          .IsRequired(true);
    }
}

As you can see, in a few minutes with the Entity Developer, we were able to create our Model visually, and all the boilerplate code for Entity classes, DbContext and Mapping was generated for us automatically.

Now you can start implementing the actual business logic.

Here is how to register our DbContext in the DI:

var connectionString = builder.Configuration.GetConnectionString("Postgres");

builder.Services.AddDbContext<ShipmentDbContext>(options =>
{
    options.EnableSensitiveDataLogging()
       .UsePostgreSql(connectionString);
});

Note that we configure the connection to the database with UsePostgreSql from the Devart.Data.PostgreSql.
This package uses dotConnect for PostgreSQL to connect to the database.

This is what the Web API endpoint for creating an Order will look like:

public static class OrderEndpoints
{
    public static WebApplication MapOrderEndpoints(this WebApplication app)
    {
        var group = app.MapGroup("/api/orders");
        group.MapPost("/", CreateOrder);
        return app;
    }

    private static async Task<IResult> CreateOrder(
        [FromBody] CreateOrderRequest request,
        ShipmentDbContext dbContext)
    {
        var shipmentId = Guid.NewGuid();
        var shipment = MapToShipment(request.Shipment, shipmentId);

        var order = MapToOrder(request, shipment);

        foreach (var productRequest in request.Products)
        {
            var product = MapToProduct(productRequest, order.Id, order);
            order.Products.Add(product);
        }

        dbContext.Orders.Add(order);
        await dbContext.SaveChangesAsync();

        var response = MapToOrderResponse(order, shipment);

        return TypedResults.Created($"/api/orders/{order.Id}", response);
    }
}

With Entity Developer, you can focus on writing the code, and all the boilerplate code for the setup is generated automatically.

Core Benefits for EF Core and PostgreSQL Development

Entity Developer doesn’t just simplify your daily tasks — it transforms the way you manage EF Core and PostgreSQL databases.

Using a Model-First approach, you visually design your database schema, and Entity Developer generates your EF Core models automatically.
This simplifies model management and synchronization between code and the database.

Entity Developer is more than just a visual modeling tool — it’s designed to solve real problems that .NET developers face when working with EF Core and PostgreSQL.

Here is how Entity Developer improves your development workflow and boosts development productivity:

  • Accelerated Development: Spend less time on boilerplate and repetitive configuration. Design, generate, and update models much faster than manual coding allows.
  • Better Collaboration: The visual Model makes it easier to share ideas and discuss changes with teammates, regardless of their EF Core experience.
  • Error Prevention: Reduce the risk of runtime errors caused by hand-written mappings or misconfigured relationships. Entity Developer generates accurate code and schema scripts for you.
  • Maintainable Codebase: Consistent, auto-generated entity and context code means easier maintenance, fewer bugs, and quicker onboarding for new team members.
  • Flexible Database Support: Switch between PostgreSQL and other supported databases as your project grows, without changing your workflow.
  • Easy Integration: Use it directly in Visual Studio or as a standalone tool.
  • PostgreSQL Optimization: Get full advantage of PostgreSQL’s unique features — like native UUIDs, JSONB, arrays, and advanced indexing — directly within your EF Core model.

By simplifying every step of the model-design-to-database workflow, Entity Developer helps you deliver projects on time and with greater confidence.

Note: Entity Developer supports the following databases: PostgreSQL, SQL Server, Oracle, MySQL, MariaDB, and SQLite.

Summary

Entity Developer by Devart, managing EF Core models and PostgreSQL databases has never been easier or faster.

Whether you’re building a new application or maintaining an existing one, its visual Model-First approach lets you focus on what matters most — solving business problems and delivering value to users.

With automatic code and SQL script generation, robust Visual Studio integration, and support for advanced PostgreSQL features, Entity Developer is a must-have tool for any .NET developer who wants to simplify their workflow and boost productivity.

Ready to transform your EF Core development process?

Download the free trial for Entity Developer, connect it to your PostgreSQL database, and see how much more productive your next project can be!

Many thanks to Devart for sponsoring this blog post.

P.S.: I publish all these blogs on my own website: Read original post here
Subscribe to my newsletter to improve your .NET skills.
Download the source code for this newsletter for free.


This content originally appeared on DEV Community and was authored by Anton Martyniuk