How the SQL to C# Model works

The converter reads your SQL with a tokenizer for the chosen dialect, finds every CREATE TABLE statement and reads its column list: each column's name, type with its length or precision, NOT NULL, PRIMARY KEY (on the column or as a table constraint), and identity markers such as IDENTITY, AUTO_INCREMENT, SERIAL or GENERATED ... AS IDENTITY. Other statements in the input, such as GO or ALTER TABLE, are skipped.

Each table becomes a class named after the table in PascalCase (optionally made singular), and each column becomes a property with a C# type chosen for that dialect. Value types for columns that allow NULL get a ?. When the property name is not exactly the column name and data annotations are on, a [Column] attribute keeps the mapping to the database. Nothing is run against a database.

How to use the SQL to C# Model

  1. Paste one or more CREATE TABLE statements into the input box, open a .sql file, or select Load example.
  2. Choose the dialect the statements were written for, then set the namespace and whether property names should be PascalCase or kept as in SQL.
  3. Tick Data annotations, Nullable reference types or Singular class names if you want them.
  4. Select Convert to C#, or press Ctrl + Enter (Cmd + Enter on a Mac), then copy the classes or download them as a .cs file.

Example

This table:

CREATE TABLE dbo.order_items (
    id INT IDENTITY(1, 1) PRIMARY KEY,
    product_name NVARCHAR(200) NOT NULL,
    unit_price DECIMAL(10, 2) NOT NULL,
    shipped_at DATETIME2 NULL
);

becomes, with the namespace MyApp.Models and the other options off:

using System;

namespace MyApp.Models
{
    public class OrderItems
    {
        public int Id { get; set; }
        public string ProductName { get; set; }
        public decimal UnitPrice { get; set; }
        public DateTime? ShippedAt { get; set; }
    }
}

With Singular class names ticked the class is named OrderItem, and with Data annotations ticked ProductName gets [Required], [MaxLength(200)] and [Column("product_name")].

Common use cases

  • Creating entity classes for an existing database table when starting an Entity Framework Core or Dapper project.
  • Keeping DTOs in step with a table after new columns were added in a migration script.
  • Turning a schema exported from SQL Server Management Studio, pg_dump or SHOW CREATE TABLE into model classes.
  • Checking which C# type a SQL column type such as DATETIMEOFFSET, TINYINT(1) or NUMERIC maps to.

Common errors and how to fix them

A CREATE TABLE statement is missing its table name
The parser reads CREATE TABLE statements, so the input must be one. Paste the full statement including the table name and the bracketed column list, not just the column lines.
Expected ( and a column list after CREATE TABLE
The statement ends before its column definitions, usually because only the first line was copied. Include everything from the opening bracket through to the matching closing bracket.
An int column was generated as int?
Nullable SQL columns map to nullable C# types. If the column should never be null, declare it NOT NULL in the source statement and generate again.
A vendor type was not recognised
Select the dialect that matches your statement before generating. Types that exist only in one database, or user-defined types, have no direct C# equivalent and need mapping by hand.

Frequently asked questions

How are SQL types mapped to C#?

Integer types map to int, long, short or byte (unsigned MySQL types to uint, ulong and so on), DECIMAL, NUMERIC and MONEY to decimal, FLOAT and REAL to double or float, BIT and BOOLEAN to bool, text types to string, date and time types to DateTime, DateTimeOffset or TimeSpan, UNIQUEIDENTIFIER and UUID to Guid, and binary types to byte[]. MySQL TINYINT(1) becomes bool, and SQL Server TIMESTAMP (a row version) becomes byte[].

How are NULL and NOT NULL columns handled?

A column is nullable unless it is NOT NULL, part of the primary key or an identity column. Nullable value types get a question mark, such as int? or DateTime?. With Nullable reference types ticked, nullable strings become string? and required strings are initialised to string.Empty.

Which data annotations are added?

With Data annotations ticked, the class gets [Table] when its name differs from the table or the table has a schema, and properties get [Key] for a single-column primary key, [DatabaseGenerated] for identity and computed columns, [Required] for NOT NULL strings and byte arrays, [MaxLength] for sized text and binary columns, and [Column] when the property name differs from the column name. Composite primary keys get a comment reminding you to configure HasKey, because [Key] cannot express them.

What if a column type is not recognised?

The property is written as object with a comment naming the SQL type, and the status message lists every type that was not mapped, so you can pick the right type yourself.

Does the tool connect to my database?

No. It only reads the CREATE TABLE text you paste. It does not run SQL or connect to any database, and the text is not uploaded to our server.