ObjMapper 0.13.4

There is a newer prerelease version of this package available.
See the version list below for details.
dotnet tool install --global ObjMapper --version 0.13.4
                    
This package contains a .NET tool you can call from the shell/command line.
dotnet new tool-manifest
                    
if you are setting up this repo
dotnet tool install --local ObjMapper --version 0.13.4
                    
This package contains a .NET tool you can call from the shell/command line.
#tool dotnet:?package=ObjMapper&version=0.13.4
                    
nuke :add-package ObjMapper --version 0.13.4
                    

omap

Database reverse engineering dotnet tool - generates entity mappings from CSV schema files or database connections for EF Core and Dapper. Features ML-based type inference, scalar UDF support, stored procedure mapping, and automatic type converters.

Automatic Dependency Submission CI CodeQL Copilot code review Copilot coding agent Release NuGet GitHub Pre-Release

Features

  • Database Schema Extraction: Extract schema directly from PostgreSQL, SQL Server, MySQL, SQLite databases
  • ML-Based Type Inference: Intelligent column type mapping using machine learning and pattern matching
  • Stored Procedure Support: Extract and generate code for stored procedures with output type detection (None, Scalar, Tabular)
  • Scalar UDF Support: Extract and generate code for user-defined scalar functions
  • View Support: Extract and generate entities for database views
  • Type Converters: Automatic generation of ValueConverters (EF Core) and TypeHandlers (Dapper) for DateOnly, TimeOnly, DateTimeOffset
  • GUID Column Detection: Automatically detect varchar(36) columns that contain GUIDs
  • Boolean Column Detection: Detect small integer columns (tinyint, smallint) that represent boolean values
  • Relationship Mapping: Full support for 1:1, 1:N, N:1, and N:M relationships
  • Index Mapping: Support for simple and composite indexes
  • Performance Options: --no-checks for faster extraction, --no-views/--no-procs/--no-udfs to skip unwanted objects

Installation

dotnet tool install --global ObjMapper

Or install as a local tool:

dotnet new tool-manifest
dotnet tool install ObjMapper

Usage

The tool supports two modes of operation:

Mode 1: CSV Files

omap <csv-file> -t <mapping-type> -d <database-type> [options]

Mode 2: Database Connection

omap --connection-string "<connection-string>" -t <mapping-type> [options]

When using a connection string, the schema is extracted directly from the database, eliminating the need for CSV files. The database type is auto-detected from the connection string.

Arguments

  • csv: CSV file with schema information (optional if using --connection-string)
    • Columns: schema, table, column, nullable, type, comment

Options

  • --connection-string, --cs: Database connection string (alternative to CSV files)

    • Schema will be extracted directly from the database
    • Database type is auto-detected when possible
  • -s, --schema: Database schema to extract (optional, used with --connection-string)

    • Default: public for PostgreSQL, dbo for SQL Server, database name for MySQL
  • -t, --type: Type of mapping to generate (required)

    • efcore: Entity Framework Core entities and configurations
    • dapper: Dapper entities and repositories
  • -d, --database: Database type (required for CSV mode, auto-detected for connection string mode)

    • mysql: MySQL
    • postgre or postgresql: PostgreSQL
    • sqlserver or mssql: SQL Server
    • oracle: Oracle
    • sqlite: SQLite
  • -f, --foreignkeys: CSV file with relationships (optional)

    • Columns: name, schema_from, schema_to, table_from, table_to, key, foreign
    • Supports composite keys (comma-separated in key and foreign columns)
    • Supports cross-schema relationships
  • -i, --indexes: CSV file with indexes (optional)

    • Columns: schema, table, name, key, type
    • Supports composite indexes (comma-separated in key column)
    • Type can be: unique, btree, hash, fulltext, etc.
  • -o, --output: Output directory for generated files (default: current directory)

  • -n, --namespace: Namespace for generated classes (default: Generated)

  • -c, --context: Name of the database context class (default: AppDbContext)

  • -e, --entity-mode: Entity generation mode (default: class)

    • class or cls: Generate as classes
    • record or rec: Generate as records
    • struct or str: Generate as structs
    • record_struct or rtr: Generate as record structs
  • -l, --locale: Locale for pluralization (default: en-us)

    • Supported locales: en-us, en-gb, en, pt-br, pt-pt, pt, es-es, es-mx, es, fr-fr, fr-ca, fr, de-de, de, it-it, it, nl-nl, nl, ru-ru, ru, pl-pl, pl, tr-tr, tr, ja-jp, ja, ko-kr, ko, zh-cn, zh-tw, zh
  • --no-pluralize: Disable pluralization/singularization

  • --no-inference: Disable ML-based type inference (enabled by default)

    • Type inference analyzes column names, types, and comments to determine the best C# type
    • Automatically detects boolean columns, GUIDs, and date/time types
  • --no-checks: Disable data sampling queries for type verification

    • When set, type inference uses only column metadata (name, type, comment)
    • Much faster schema extraction but may be less accurate for edge cases
    • Name-based inference is still applied (e.g., is_active → bool)
  • --no-views: Disable view mapping

    • Views will not be extracted from the database
  • --no-procs: Disable stored procedure mapping

    • Stored procedures will not be extracted from the database
  • --no-udfs: Disable user-defined function mapping

    • Scalar functions will not be extracted from the database
  • --no-rel: Disable relationship mapping

    • Foreign key relationships will not be extracted
    • Cannot be used together with --legacy
  • --legacy: Enable legacy relationship inference

    • Infers relationships from column/table naming patterns when no foreign keys exist
    • Detects patterns: user_idusers table, fk_customercustomer table
    • Supports singular/plural table name matching
    • Cannot be used together with --no-rel

Configuration

The tool supports configuration files at two levels:

Global Configuration

Located at ~/.omap/config.json. Created automatically on first run.

{
  "locale": "en-us",
  "noPluralizer": false,
  "namespace": "MyApp.Data",
  "database": "postgresql",
  "type": "efcore",
  "entityMode": "class",
  "context": "AppDbContext"
}

Local Configuration

Place a .omap/config.json file in your project directory (or any parent directory). Local settings override global settings.

Priority

Settings are applied in this order (later overrides earlier):

  1. Default values
  2. Global configuration (~/.omap/config.json)
  3. Local configuration (.omap/config.json found recursively)
  4. Command-line arguments

Configuration Commands

# Set a configuration value (global by default)
omap config set locale pt-br
omap config set namespace MyApp.Data
omap config set database postgresql

# Set a local configuration value
omap config set locale pt-br --local

# Remove a configuration value
omap config unset namespace
omap config unset namespace --local

# List all configuration values
omap config list

# Show configuration file paths
omap config path
omap config path --local
omap config path --global

Available configuration keys:

  • locale / l - Locale for pluralization
  • namespace / n - Namespace for generated classes
  • database / d - Database type
  • type / t - Mapping type (efcore/dapper)
  • entity-mode / e - Entity generation mode
  • context / c - Database context name
  • no-pluralize - Disable pluralization (true/false)

Examples

Generate EF Core mappings from CSV

omap schema.csv -t efcore -d postgresql -o ./Generated -n MyApp.Data

Generate from database connection

# PostgreSQL
omap --cs "Host=localhost;Database=mydb;Username=user;Password=pass" -t efcore -o ./Generated

# MySQL
omap --cs "Server=localhost;Database=mydb;User=user;Password=pass" -t dapper -o ./Generated

# SQL Server
omap --cs "Server=localhost;Database=mydb;User Id=user;Password=pass;TrustServerCertificate=True" -t efcore -o ./Generated

# SQLite
omap --cs "Data Source=mydb.sqlite" -t efcore -o ./Generated

# With schema filter
omap --cs "Host=localhost;Database=mydb;Username=user;Password=pass" -t efcore -s sales -o ./Generated

Generate Dapper mappings with relationships and indexes

omap schema.csv -t dapper -d mysql -f relationships.csv -i indexes.csv -o ./Generated -n MyApp.Data -c MyDbContext

Generate as records

omap schema.csv -t efcore -d sqlserver -e record -o ./Generated -n MyApp.Data

Use Portuguese pluralization

omap schema.csv -t efcore -d postgresql -l pt-br -o ./Generated -n MyApp.Data

Disable pluralization

omap schema.csv -t efcore -d postgresql --no-pluralize -o ./Generated -n MyApp.Data

CSV File Formats

Schema CSV (schema.csv)

schema,table,column,nullable,type,comment
public,users,id,false,int,Primary key
public,users,name,false,varchar(100),User name
public,users,email,true,varchar(255),Email address
public,users,created_at,false,timestamp,Creation timestamp
public,orders,id,false,int,Primary key
public,orders,user_id,false,int,Foreign key to users
public,orders,total,false,decimal(10,2),Order total

Relationships CSV (relationships.csv)

name,schema_from,schema_to,table_from,table_to,key,foreign
fk_orders_users,public,public,orders,users,id,user_id

For composite keys:

name,schema_from,schema_to,table_from,table_to,key,foreign
fk_composite,public,public,order_items,orders,"order_id,product_id","order_id,product_id"

Indexes CSV (indexes.csv)

schema,table,name,key,type
public,users,idx_users_email,email,unique
public,orders,idx_orders_user_id,user_id,btree

Output Structure

The tool generates the following files (all types are partial):

output/
├── Entities/
│   ├── User.cs
│   └── Order.cs
├── Configurations/
│   ├── UserConfiguration.cs      # EF Core only
│   ├── OrderConfiguration.cs     # EF Core only
│   ├── UserRepository.cs         # Dapper only
│   └── OrderRepository.cs        # Dapper only
├── Converters/                   # Generated when using DateOnly, TimeOnly, DateTimeOffset
│   ├── DateOnlyConverter.cs      # EF Core ValueConverter
│   ├── TimeOnlyConverter.cs      # EF Core ValueConverter
│   ├── DateTimeOffsetConverter.cs # EF Core ValueConverter
│   └── DapperTypeHandlers.cs     # Dapper TypeHandlers + registration
├── Functions/                    # Generated when scalar UDFs exist
│   ├── ScalarFunctions.cs        # EF Core [DbFunction] stubs
│   └── ScalarFunctionRepository.cs # Dapper ExecuteScalar wrappers
└── AppDbContext.cs

Type Inference

Type inference is enabled by default and uses ML.NET combined with pattern matching to determine the best C# type for each column. Use --no-inference to disable.

Pattern-Based Inference

The tool recognizes common column naming patterns:

Pattern Inferred Type
is_*, has_*, *_flag, active, enabled, deleted bool
uuid, *_guid, *_uuid, correlation_id, tracking_id Guid
*_at, *_date, created, updated, deleted_at DateTime / DateOnly
*_time TimeOnly

Boolean Column Detection (Connection String Mode)

When using --connection-string (or --cs), the tool queries small integer columns (tinyint, smallint, bit) to check if they only contain NULL, 0, or 1 values. If so, they are mapped to bool.

-- Example: Column "is_active TINYINT" with values {0, 1} → bool
-- The tool runs: SELECT DISTINCT is_active FROM users WHERE is_active IS NOT NULL

GUID Column Detection (Connection String Mode)

When using --connection-string (or --cs), varchar(36) and char(36) columns are analyzed for valid GUID values:

  • Requires at least 10 valid GUID values
  • Must not contain any blank or whitespace-only values
  • If conditions are met, the column is mapped to Guid
// Column "tracking_id VARCHAR(36)" with valid GUIDs → Guid
public Guid TrackingId { get; set; }

CSV Mode

In CSV mode, char(36) columns are automatically mapped to Guid. Additional inference based on column names is still applied.

Scalar User-Defined Functions

The tool extracts scalar user-defined functions (UDFs) from the database and generates appropriate code:

EF Core

Generates static methods with [DbFunction] attribute:

public static partial class ScalarFunctions
{
    [DbFunction("calculate_tax", "dbo")]
    public static decimal CalculateTax(decimal amount, decimal rate)
        => throw new NotSupportedException("This method is for use in LINQ queries only.");
}

Register in your DbContext:

modelBuilder.HasDbFunction(typeof(ScalarFunctions).GetMethod(nameof(ScalarFunctions.CalculateTax)));

Dapper

Generates repository methods with sync and async variants:

public partial class ScalarFunctionRepository(IDbConnection connection)
{
    public decimal CalculateTax(decimal amount, decimal rate)
    {
        return connection.ExecuteScalar<decimal>(
            "SELECT dbo.calculate_tax(@Amount, @Rate)",
            new { Amount = amount, Rate = rate });
    }
    
    public async Task<decimal> CalculateTaxAsync(decimal amount, decimal rate)
    {
        return await connection.ExecuteScalarAsync<decimal>(
            "SELECT dbo.calculate_tax(@Amount, @Rate)",
            new { Amount = amount, Rate = rate });
    }
}

Stored Procedures

The tool extracts stored procedures from the database and generates appropriate code based on the detected output type:

Output Type Detection

  • None: Procedures that don't return any value
  • Scalar: Procedures with OUT parameters (returns single value)
  • Tabular: Procedures that return result sets (SELECT statements)

EF Core

Generates DbContext extension methods:

public static partial class StoredProcedureExtensions
{
    // Void procedure (no output)
    public static void CleanupOldData(this DbContext context, DateTime olderThan)
    {
        context.Database.ExecuteSqlRaw("EXEC dbo.CleanupOldData @OlderThan", 
            new SqlParameter("@OlderThan", olderThan));
    }
    
    public static async Task CleanupOldDataAsync(this DbContext context, DateTime olderThan, 
        CancellationToken cancellationToken = default)
    {
        await context.Database.ExecuteSqlRawAsync("EXEC dbo.CleanupOldData @OlderThan", 
            new SqlParameter("@OlderThan", olderThan), cancellationToken);
    }
    
    // Tabular procedure (returns result set)
    public static List<GetOrdersByDateResult> GetOrdersByDate(this DbContext context, DateTime orderDate)
    {
        return context.Set<GetOrdersByDateResult>()
            .FromSqlRaw("EXEC dbo.GetOrdersByDate @OrderDate", 
                new SqlParameter("@OrderDate", orderDate))
            .ToList();
    }
}

// Result type for tabular procedures
[Keyless]
public class GetOrdersByDateResult
{
    public int OrderId { get; set; }
    public DateTime OrderDate { get; set; }
    public decimal TotalAmount { get; set; }
}

Dapper

Generates IDbConnection extension methods:

public static partial class StoredProcedureExtensions
{
    // Void procedure
    public static void CleanupOldData(this IDbConnection connection, DateTime olderThan)
    {
        connection.Execute("dbo.CleanupOldData", new { olderThan }, 
            commandType: CommandType.StoredProcedure);
    }
    
    // Tabular procedure
    public static IEnumerable<GetOrdersByDateResult> GetOrdersByDate(
        this IDbConnection connection, DateTime orderDate)
    {
        return connection.Query<GetOrdersByDateResult>("dbo.GetOrdersByDate", 
            new { orderDate }, commandType: CommandType.StoredProcedure);
    }
    
    public static async Task<IEnumerable<GetOrdersByDateResult>> GetOrdersByDateAsync(
        this IDbConnection connection, DateTime orderDate)
    {
        return await connection.QueryAsync<GetOrdersByDateResult>("dbo.GetOrdersByDate", 
            new { orderDate }, commandType: CommandType.StoredProcedure);
    }
}

Type Converters

The tool automatically generates type converters for types not natively supported by all database drivers:

DateOnly, TimeOnly, DateTimeOffset

Some database drivers don't natively support DateOnly, TimeOnly, or DateTimeOffset. The tool generates:

EF Core ValueConverters:

public class DateOnlyConverter : ValueConverter<DateOnly, DateTime>
{
    public DateOnlyConverter() : base(
        d => d.ToDateTime(TimeOnly.MinValue),
        d => DateOnly.FromDateTime(d))
    { }
}

Dapper TypeHandlers:

public class DateOnlyTypeHandler : SqlMapper.TypeHandler<DateOnly>
{
    public override DateOnly Parse(object value) => DateOnly.FromDateTime((DateTime)value);
    public override void SetValue(IDbDataParameter parameter, DateOnly value)
    {
        parameter.Value = value.ToDateTime(TimeOnly.MinValue);
        parameter.DbType = DbType.Date;
    }
}

// Registration helper
public static class DapperTypeHandlerRegistration
{
    public static void RegisterAll()
    {
        SqlMapper.AddTypeHandler(new DateOnlyTypeHandler());
        SqlMapper.AddTypeHandler(new TimeOnlyTypeHandler());
        SqlMapper.AddTypeHandler(new DateTimeOffsetTypeHandler());
    }
}

DateTimeOffset Mapping

The tool maps database types to DateTimeOffset when appropriate:

Database Type C# Type
PostgreSQL timestamptz DateTimeOffset
SQL Server datetimeoffset DateTimeOffset

Pluralization

The tool supports pluralization and singularization in multiple languages:

Language Locales
English en-us, en-gb, en
Portuguese pt-br, pt-pt, pt
Spanish es-es, es-mx, es
French fr-fr, fr-ca, fr
German de-de, de
Italian it-it, it
Dutch nl-nl, nl
Russian ru-ru, ru
Polish pl-pl, pl
Turkish tr-tr, tr
Japanese ja-jp, ja
Korean ko-kr, ko
Chinese zh-cn, zh-tw, zh

Note: Japanese, Korean, and Chinese don't typically have plural forms, so pluralization is disabled for these languages.

Versioning

The tool uses semantic versioning with support for preview versions:

  • Release: 1.0.0
  • Beta: 1.0.0-beta1
  • Release Candidate: 1.0.0-rc1

License

MIT License - see LICENSE for details.

Product Compatible and additional computed target framework versions.
.NET net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

This package has no dependencies.

Version Downloads Last Updated
1.0.0-alpha.2 146 12/6/2025
0.13.4 423 12/8/2025
0.10.4 417 12/8/2025