Skip to main content

Command Palette

Search for a command to run...

Data API Builder (DAB) in .NET: Turn your DB into REST + GraphQL in minutes 🚀

Updated
•5 min read
N
Software development lead & designer with a demonstrated history of working in the information technology and services industry. Skilled in C#, Dotnet Core, Kubernetes, Microservices, Azure DevOps, GitHub Actions, Microsoft Azure PaaS/IaaS, SQL & No-SQL Databases, JavaScript . Extensive experience in designing & developing complex web api & system applications with microservice architectures.

If you’ve ever built the same CRUD endpoints over and over, Data API Builder (DAB) is a breath of fresh air. It’s an open-source, configuration-based engine that can expose your database objects as secure REST and GraphQL APIs—without writing a custom web API.

DAB runs as a stateless service (great for containers), supports popular databases (SQL Server/Azure SQL, PostgreSQL, MySQL, Cosmos DB, etc.), and ships with a handy .NET CLI tool to bootstrap configs and entities quickly.

Why you might like it ?

  • REST + GraphQL out of the box

  • One JSON config file controls runtime + entities (no “API project” required)

  • Dev-friendly extras like OpenAPI/Swagger, telemetry (OpenTelemetry), health checks

Lets build an Order Management API in minutes with Data API Builder (DAB)

When you’re building internal tools (procurement, order tracking, inventory, chargeback portals), you often need the same stuff:

  • CRUD endpoints

  • filtering/sorting/pagination

  • clean relationships (Orders → Items → Product)

  • REST for simple consumers + GraphQL for flexible UI queries

Data API Builder (DAB) gives you REST and GraphQL endpoints directly over your database with a configuration-first approach.

Create table schema's for “Orders” API (Customers, Orders, OrderItems, Products)

CREATE TABLE dbo.Customer (
  CustomerId INT IDENTITY PRIMARY KEY,
  Name NVARCHAR(200) NOT NULL,
  Email NVARCHAR(320) NOT NULL UNIQUE
);

CREATE TABLE dbo.Product (
  ProductId INT IDENTITY PRIMARY KEY,
  Sku NVARCHAR(50) NOT NULL UNIQUE,
  Name NVARCHAR(200) NOT NULL,
  Price DECIMAL(10,2) NOT NULL
);

CREATE TABLE dbo.[Order] (
  OrderId INT IDENTITY PRIMARY KEY,
  CustomerId INT NOT NULL,
  Status NVARCHAR(30) NOT NULL DEFAULT 'Created',
  CreatedUtc DATETIME2 NOT NULL DEFAULT SYSUTCDATETIME(),
  CONSTRAINT FK_Order_Customer FOREIGN KEY (CustomerId) REFERENCES dbo.Customer(CustomerId)
);

CREATE TABLE dbo.OrderItem (
  OrderItemId INT IDENTITY PRIMARY KEY,
  OrderId INT NOT NULL,
  ProductId INT NOT NULL,
  Quantity INT NOT NULL,
  UnitPrice DECIMAL(10,2) NOT NULL,
  CONSTRAINT FK_OrderItem_Order FOREIGN KEY (OrderId) REFERENCES dbo.[Order](OrderId),
  CONSTRAINT FK_OrderItem_Product FOREIGN KEY (ProductId) REFERENCES dbo.Product(ProductId)
);

Install DAB CLI + create config

Install the Data API Builder (DAB) tool.

dotnet tool install microsoft.dataapibuilder -g

Initialize the configuration for DAB.

dab init --database-type "mssql" --host-mode "Development" \
  --connection-string "Server=localhost;Database=OrdersDb;User Id=sa;Password=Your_password123;TrustServerCertificate=True;"

Add entities (tables) with permissions

Data API builder support different authentication & authorization schemes, for ease of this blog, I am considering the implementation to have no auth. Will introduce future post with more inputs towards auth across the APIs exposed by DAB.

dab add Customer  --source "dbo.Customer"  --permissions "anonymous:*"
dab add Product   --source "dbo.Product"   --permissions "anonymous:*"
dab add Order     --source "dbo.[Order]"   --permissions "anonymous:*"
dab add OrderItem --source "dbo.OrderItem" --permissions "anonymous:*"

Realistic DAB config with relationships (dab-config.json)

DAB is configuration-based: you describe the data source, runtime, and exposed entities in one JSON file.
By default, REST commonly sits under /api and GraphQL under /graphql (configurable).

{
  "data-source": {
    "database-type": "mssql",
    "connection-string": "Server=localhost;Database=OrdersDb;User Id=sa;Password=Your_password123;TrustServerCertificate=True;"
  },
  "runtime": {
    "rest": { "enabled": true, "path": "/api" },
    "graphql": { "enabled": true, "path": "/graphql", "allow-introspection": true },
    "host": { "mode": "development" }
  },
  "entities": {
    "Customer": {
      "source": "dbo.Customer",
      "permissions": [
        { "role": "anonymous", "actions": [ "*" ] }
      ],
      "relationships": {
        "Orders": {
          "cardinality": "many",
          "target.entity": "Order",
          "relationship.fields": { "CustomerId": "CustomerId" }
        }
      }
    },
    "Order": {
      "source": "dbo.[Order]",
      "permissions": [
        { "role": "anonymous", "actions": [ "*" ] }
      ],
      "relationships": {
        "Customer": {
          "cardinality": "one",
          "target.entity": "Customer",
          "relationship.fields": { "CustomerId": "CustomerId" }
        },
        "Items": {
          "cardinality": "many",
          "target.entity": "OrderItem",
          "relationship.fields": { "OrderId": "OrderId" }
        }
      }
    },
    "OrderItem": {
      "source": "dbo.OrderItem",
      "permissions": [
        { "role": "anonymous", "actions": [ "*" ] }
      ],
      "relationships": {
        "Order": {
          "cardinality": "one",
          "target.entity": "Order",
          "relationship.fields": { "OrderId": "OrderId" }
        },
        "Product": {
          "cardinality": "one",
          "target.entity": "Product",
          "relationship.fields": { "ProductId": "ProductId" }
        }
      }
    },
    "Product": {
      "source": "dbo.Product",
      "permissions": [
        { "role": "anonymous", "actions": [ "*" ] }
      ]
    }
  }
}

(Relationship syntax is where people often vary their config—this example shows the intent clearly: navigate Order → Items → Product and Customer → Orders.)

Start DAB

dab start

Now you have:

  • REST at http://localhost:<port>/api/...

  • GraphQL at http://localhost:<port>/graphql

Both these Endpoints provide the ability to interact with the database entities directly without having to spin up a WebAPI.

Benefits of using DAB

  • Zero (or near-zero) API code

  • REST and GraphQL from the same backend

  • Excellent developer velocity

  • Built-in API features you’d normally reimplement (filtering, pagination, sorting, field projection, openapi specs, authentication

  • Secure by design (Role-based permissions per entity/action, JWT, Row-level security patterns)

  • Stateless & can be easily containerized.

  • Best use cases are around databases exposing analytical data, reporting & streaming services.

Cons of using DAB

  • Not ideal for complex business logic

  • Less flexibility than a custom API

  • Config complexity grows with scale

  • Debugging is less familiar

  • Performance tuning is indirect

  • Opinionated CRUD model

TL;DR

DAB is not a replacement for all APIs.
It’s a highly effective data API engine when your needs are CRUD-heavy, schema-driven, and security-aware.