Writing a CREATE TABLE statement by hand from a C# class is mechanical work. Each property becomes a column, the types need to be translated, primary keys and nullability need to be inferred, and you need to pick the right syntax for your target database. It’s not hard, but it’s slow and repetitive.
The C# to SQL converter automates this translation. You paste the class, pick your dialect, and get a ready-to-use DDL statement.
A Complete Example
Input:
public class Product
{
public int Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public decimal Price { get; set; }
public int StockQuantity { get; set; }
public bool IsActive { get; set; }
public DateTime CreatedAt { get; set; }
public DateTime? UpdatedAt { get; set; }
public Guid ExternalId { get; set; }
}
Output (PostgreSQL dialect):
CREATE TABLE product (
id SERIAL PRIMARY KEY,
name TEXT NOT NULL,
description TEXT NOT NULL,
price NUMERIC(18, 2) NOT NULL,
stock_quantity INTEGER NOT NULL,
is_active BOOLEAN NOT NULL,
created_at TIMESTAMP NOT NULL,
updated_at TIMESTAMP,
external_id UUID NOT NULL
);
Output (T-SQL / SQL Server):
CREATE TABLE [Product] (
[Id] INT IDENTITY(1,1) PRIMARY KEY,
[Name] NVARCHAR(255) NOT NULL,
[Description] NVARCHAR(255) NOT NULL,
[Price] DECIMAL(18, 2) NOT NULL,
[StockQuantity] INT NOT NULL,
[IsActive] BIT NOT NULL,
[CreatedAt] DATETIME2 NOT NULL,
[UpdatedAt] DATETIME2 NULL,
[ExternalId] UNIQUEIDENTIFIER NOT NULL
);
Two different outputs from the same input — each using the correct syntax, type names, and quoting conventions for its dialect.
Type Mapping: C# to SQL
Here’s how the most common C# types translate across dialects:
| C# type | SQL Server | PostgreSQL | MySQL |
|---|---|---|---|
int | INT | INTEGER | INT |
long | BIGINT | BIGINT | BIGINT |
string | NVARCHAR(255) | TEXT | VARCHAR(255) |
bool | BIT | BOOLEAN | TINYINT(1) |
decimal | DECIMAL(18,2) | NUMERIC(18,2) | DECIMAL(18,2) |
double | FLOAT | DOUBLE PRECISION | DOUBLE |
float | REAL | REAL | FLOAT |
DateTime | DATETIME2 | TIMESTAMP | DATETIME |
DateTimeOffset | DATETIMEOFFSET | TIMESTAMPTZ | DATETIME |
Guid | UNIQUEIDENTIFIER | UUID | CHAR(36) |
byte[] | VARBINARY(MAX) | BYTEA | BLOB |
Nullable types (e.g., int?, DateTime?) map to the same SQL type but without NOT NULL.
Primary Key Inference
The converter applies a simple rule: a property named Id or <ClassName>Id is treated as the primary key.
intorlongprimary key → identity/serial semantics:IDENTITY(1,1)(T-SQL),SERIAL(PostgreSQL),AUTO_INCREMENT(MySQL)Guidprimary key → no auto-generation; Guids are typically generated in application code
public class Customer
{
public int CustomerId { get; set; } // → PRIMARY KEY with identity
public string Name { get; set; }
}
public class Session
{
public Guid Id { get; set; } // → PRIMARY KEY, no auto-increment
public DateTime StartedAt { get; set; }
}
Column Naming Conventions
The converter applies dialect-appropriate naming:
- PostgreSQL →
snake_case(PostgreSQL convention, and the default Npgsql behavior) - T-SQL / SQL Server →
PascalCasewith bracket quoting - MySQL →
snake_casewith backtick quoting
If your team uses a different naming convention, treat the output as a starting point and adjust column names.
What the Three Dialects Produce Differently
T-SQL (SQL Server)
- Bracket quoting:
[ColumnName] - String type:
NVARCHAR(255)(Unicode by default) - Bool:
BIT - Guid:
UNIQUEIDENTIFIER - Date:
DATETIME2 - Identity:
IDENTITY(1,1)
PostgreSQL
- Double-quote or unquoted column names; snake_case is standard
- String type:
TEXT(no length limit) - Bool:
BOOLEAN - Guid:
UUID - Date:
TIMESTAMPorTIMESTAMPTZ - Serial:
SERIAL(orGENERATED ALWAYS AS IDENTITYin newer PostgreSQL)
MySQL
- Backtick quoting:
`column_name` - String type:
VARCHAR(255) - Bool:
TINYINT(1)(MySQL doesn’t have a true boolean; TINYINT(1) is the convention) - Guid:
CHAR(36)(MySQL has no native UUID type in older versions) - Date:
DATETIME - Auto increment:
AUTO_INCREMENT
Practical Uses
Bootstrapping a new table
You’ve designed a domain entity in C#. Before writing migrations or using EF Core, you want to see what the table should look like. Paste the class, pick your database, and get the DDL. Review it, adjust column lengths or types, then use it in your migration script or apply it directly.
Reverse engineering for documentation
You have existing C# entities and no database documentation. Generate the corresponding CREATE TABLE for each entity. This is often faster than navigating a database schema viewer when you’re trying to explain the data model to a new team member.
Database-first teams working with C# code
If your database team is writing the schema and you need to make sure the C# model aligns, run both through the tool (C# → SQL and compare, or SQL → check manually) to confirm the type mappings are consistent.
Cross-database migrations
You’re moving from SQL Server to PostgreSQL. Paste the T-SQL entity class and generate PostgreSQL output. Use it as a starting point for the PostgreSQL migration script.
Known Limitations
Navigation properties are not mapped. Entity Framework navigation properties like:
public virtual ICollection<OrderItem> Items { get; set; }
public virtual Customer Customer { get; set; }
…are not included in the DDL output. The generator focuses on scalar properties. Foreign key columns are not automatically inferred from navigation properties.
No indexes, constraints, or defaults. The output is a basic CREATE TABLE. Indexes, UNIQUE constraints, CHECK constraints, and column defaults are not generated.
No EF Core annotations. [MaxLength], [Column("custom_name")], [Table("custom_table")] are not read. The output uses the property name directly.
Complex types and value objects (like EF Core owned entities) are not expanded.
For production DDL, start with the generated output and add the above as needed.
Workflow Tip: Format the Output
The generated SQL is functional but not always perfectly indented for your team’s style. After generating, paste the output into the SQL Formatter and pick your dialect — this gives you cleanly indented DDL that’s ready for a migration file or a pull request.
If your data originates from a JSON API rather than a C# model, the JSON to SQL guide covers the same DDL scaffolding from a JSON object. And if you need sample JSON payloads from the same C# entities, the C# to JSON guide generates those in one step.
The C# to SQL converter is most useful during the design phase — when you’re thinking about data models and want to see the database side of the picture without switching contexts. Generate the DDL, run it against a local database, and iterate on the C# model and schema together.