⇄ Code & API Conversion

SQL CREATE TABLE to C# Entity Class (EF Core)

Turn CREATE TABLE statements from SQL Server, PostgreSQL, MySQL or SQLite into EF Core entity classes — data annotations, Fluent API, or plain POCOs.

4 SQL dialects EF Core attributes or Fluent API Foreign key navigation Reads SSMS scripts

Loading SQL → C#…

What this page sends

  • Your input: Processed in this tab and not sent to a server.
  • Share links: Share links put a Base64 copy of your input and output in the URL itself (after #d=). Anyone with the link can read it, so don't share a link that contains secrets.
  • Editor: On desktop screens the code editor (Monaco) is downloaded from cdn.jsdelivr.net; phones get a built-in lightweight editor instead.
  • Page load: Loading the page requests HTML, scripts and images from ByteKiln, fonts from Google Fonts, and sends Google Analytics page views, tool-usage events and catalog interactions (tool/category IDs, result status and whether a click followed search — never your input, output or search terms). Privacy & sharing

How the SQL CREATE TABLE to C# Entity Class (EF Core) Works

Generating an entity class from a table sounds mechanical until you meet real DDL. A script exported from SQL Server Management Studio puts types in brackets, splits foreign keys and defaults into separate ALTER TABLE statements and separates batches with GO. pg_dump declares sequences and primary keys after the table. MySQL dumps carry backticks, UNSIGNED, AUTO_INCREMENT and table options, and in SQLite a column does not even need a type. On top of the syntax, every dialect maps types differently: SQL Server's timestamp is a row version rather than a date, MySQL's tinyint(1) is really a boolean, and PostgreSQL folds unquoted identifiers to lower case, so a table written as Users is actually named users. This converter parses the statements with a purpose-built tokenizer for each of the four dialects, keeps only CREATE TABLE and the ALTER TABLE constraints that belong to them, and generates C# that EF Core can map without surprises: correct nullability, keys, identity columns, [Column] names where C# naming differs, and navigation properties for foreign keys between tables in the same script.

Parsing

A dialect-aware tokenizer handles [brackets], "double quotes", `backticks`, N'…' and E'…' strings, $$ dollar quoting, nested comments and GO batch separators. Each CREATE TABLE is parsed into columns and constraints; when a statement can't be parsed, you get the line and column, and the columns are still extracted with a simpler pattern and clearly labelled best effort.

Type mapping

Each dialect has its own map: decimal(p,s) keeps its precision through [Column(TypeName = …)], varchar in SQL Server gets [Unicode(false)], SQLite falls back to its type-affinity rules, and date/time columns become DateOnly/TimeOnly or DateTime/TimeSpan depending on the option. Nullable columns become T? for value types and string? when nullable reference types are on.

Keys and generated values

IDENTITY, AUTO_INCREMENT, SERIAL, GENERATED … AS IDENTITY, nextval() defaults and SQLite INTEGER PRIMARY KEY all become DatabaseGeneratedOption.Identity. An integer key without identity gets DatabaseGeneratedOption.None, because EF would otherwise assume the database generates it. Computed columns become Computed, and rowversion columns get [Timestamp].

Names and relationships

snake_case becomes PascalCase with the original name kept in [Column("…")]. Keywords, leading digits, spaces and a property named like its class are sanitized. Foreign keys to a table in the same script add a reference navigation on the dependent side and a collection on the principal side, with [InverseProperty] so multiple foreign keys to the same table stay unambiguous.

Limitations

  • It reads CREATE TABLE and the ALTER TABLE statements that add keys and defaults; views, stored procedures, triggers, check constraints and computed-column expressions are ignored.
  • Relationships come only from foreign keys in the same script. Many-to-many join tables are generated as entities, not as skip navigations.
  • Defaults are written as comments rather than C# initializers, and database collations, sequences and indexes other than keys are not configured in Fluent API.
  • It is a starting point for dotnet ef dbcontext scaffold-style code, not a replacement: scaffolding against the live database sees everything.

FAQ

Short answers for the things developers usually ask before trusting a tool.

Is my SQL schema uploaded anywhere?

No. The CREATE TABLE statements are tokenized and parsed in your browser, and the C# is generated there too. Nothing is sent to a server, and no database connection is made — the tool only reads the text you paste.

How is this different from dotnet ef dbcontext scaffold?

Scaffolding connects to a live database and generates every table plus a DbContext. This tool works from a script, so it is useful when you only have DDL (a migration file, a pull request, a schema from documentation), when you want one or two tables rather than the whole database, or when you can't reach the server from your machine.

Which SQL dialects and types are supported?

SQL Server (T-SQL), PostgreSQL, MySQL/MariaDB and SQLite, auto-detected from the script with a manual override. Types map to the CLR types EF Core providers use — for example nvarchar(256) becomes string with [MaxLength(256)], datetimeoffset and timestamptz become DateTimeOffset, uniqueidentifier and uuid become Guid, rowversion becomes byte[] with [Timestamp], and MySQL tinyint(1) becomes bool. Unknown types become object with a warning.

What happens with composite primary keys or tables without a key?

A composite key is emitted as [PrimaryKey(nameof(A), nameof(B))] on the class, which needs EF Core 7 or later; a comment shows the HasKey Fluent API alternative for older versions. A table with no primary key gets [Keyless] and a warning, because EF Core can read but not track or update keyless entities.

Does it read SSMS "Script Table as CREATE" output?

Yes. Bracketed names and types ([dbo].[Users], [nvarchar](256)), GO separators, CONSTRAINT … DEFAULT clauses, PERSISTED computed columns, ON [PRIMARY], and the ALTER TABLE … ADD CONSTRAINT FOREIGN KEY and ADD DEFAULT … FOR statements that SSMS writes separately are all understood. pg_dump's ALTER TABLE ONLY … ADD CONSTRAINT and SET DEFAULT nextval(…) are handled too.

Why are defaults written as comments instead of C# initializers?

Database defaults like GETDATE(), now() or NEWID() run in the database at insert time. Translating them into C# initializers would change when and where the value is created, so the SQL default is kept as a comment. In Fluent API mode the comment reminds you where HasDefaultValueSql belongs if EF should know about it.

Related tools

Useful follow-ups when one conversion usually turns into three more.

Want the background and worked examples? There's a longer write-up.

Read the SQL → C# guide