efx new Product: One Command to Scaffold EF Core & Apply Migrations

Abierto
#39,569 9 comentarios 9 reacciones 0 asignados Ver en GitHub

Los mantenedores suelen responder en 2 días

Nadie ha tomado este issue todavía.

Evaluación

Dificultad
5/5
Tiempo estimado
Más de una semana
Aptitud para principiantes
35/100
Tipo de issue
Nueva funcionalidad
Claridad
Bastante claro
Estado de actividad
Activo
Stack tecnológico
csharp

Línea de trabajo

Start by reading the EF Core CLI and migration tooling documentation to identify the existing command entry points; the issue does not name files or tests. Determine whether model scaffolding and combined migration execution fit the CLI's scope, then discuss the proposed command behavior with maintainers. Done means the supported command behavior and scope are agreed before implementation.

Escrito por el modelo de indexación a partir del texto del issue.

Descripción

customer-reported
WhatsApp Image 2026-11-12 at 9 48 34 AM (1)

EFX: Scaffold EF Core Entities and Apply Migrations in One Command

Every time I add a new entity in EF Core, I end up repeating the exact same boilerplate routine:

  1. Create a new .cs file in the Entities folder.
  2. Add the class and a primary key.
  3. Open DbContext and wire up a new DbSet<T>.
  4. Run dotnet ef migrations add ...
  5. Run dotnet ef database update
    None of these steps are hard, they're just repetitive friction—especially during early prototyping when the schema changes every ten minutes.
    To speed this up, I built a small .NET global tool prototype called EFX to collapse the whole workflow into a single command:
efx new Product

What it does under the hood

When you run the command from your project directory, it:

  • Creates an Entities/ folder (if missing) and generates Product.cs with a default Id.
  • Locates AppDbContext.cs and injects public DbSet<Product> Products => Set<Product>();.
  • Shells out to dotnet ef migrations add AddProduct.
  • Runs dotnet ef database update immediately after.

Project Setup

It's a single-file console app packed as a standard .NET tool.

EFX/
├── EFX.csproj
└── Program.cs

EFX.csproj

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net8.0</TargetFramework>
    <PackAsTool>true</PackAsTool>
    <ToolCommandName>efx</ToolCommandName>
    <PackageId>EFX.Tool</PackageId>
    <Version>1.0.0</Version>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
  </PropertyGroup>

</Project>

Program.cs

using System.Diagnostics;

const string marker = "// <EFX-DBSETS>";

if (args.Length < 2 || args[0] != "new")
{
    Console.WriteLine("Usage: efx new <EntityName>");
    return;
}

var entityName = args[1];
var contextName = "AppDbContext";

var contextPath = Directory
    .GetFiles(".", $"{contextName}.cs", SearchOption.AllDirectories)
    .FirstOrDefault(p =>
        !p.Contains($"{Path.DirectorySeparatorChar}bin{Path.DirectorySeparatorChar}") &&
        !p.Contains($"{Path.DirectorySeparatorChar}obj{Path.DirectorySeparatorChar}"));

if (contextPath is null)
{
    Console.WriteLine("DbContext file was not found.");
    return;
}

var entitiesDirectory = Path.Combine(".", "Entities");
Directory.CreateDirectory(entitiesDirectory);

var entityPath = Path.Combine(entitiesDirectory, $"{entityName}.cs");

if (File.Exists(entityPath))
{
    Console.WriteLine("Entity already exists.");
    return;
}

// 1. Generate the entity
var entityCode = $"""
namespace App.Entities;

public class {entityName}
{{
    public int Id {{ get; set; }}
}}
""";

await File.WriteAllTextAsync(entityPath, entityCode);
Console.WriteLine($"Created: {entityPath}");

// 2. Register the DbSet
var contextCode = await File.ReadAllTextAsync(contextPath);

if (!contextCode.Contains(marker))
{
    Console.WriteLine($"Add the marker {marker} inside your DbContext first.");
    File.Delete(entityPath);
    return;
}

if (!contextCode.Contains("using App.Entities;"))
{
    contextCode = "using App.Entities;\n" + contextCode;
}

var dbSetCode = $"public DbSet<{entityName}> {entityName}s => Set<{entityName}>();";
contextCode = contextCode.Replace(marker, $"{dbSetCode}\n    {marker}");

await File.WriteAllTextAsync(contextPath, contextCode);
Console.WriteLine($"Registered DbSet<{entityName}>");

// 3. Create and apply migration
var migrationName = $"Add{entityName}";

if (await RunCommand("dotnet", "ef", "migrations", "add", migrationName) != 0)
{
    Console.WriteLine("Migration creation failed.");
    return;
}

if (await RunCommand("dotnet", "ef", "database", "update") != 0)
{
    Console.WriteLine("Database update failed. Check the generated migration.");
    return;
}

Console.WriteLine($"Successfully created {entityName} and updated the database.");

static async Task<int> RunCommand(string file, params string[] arguments)
{
    var startInfo = new ProcessStartInfo(file)
    {
        UseShellExecute = false
    };

    foreach (var argument in arguments)
        startInfo.ArgumentList.Add(argument);

    using var process = Process.Start(startInfo);
    if (process is null) return -1;

    await process.WaitForExitAsync();
    return process.ExitCode;
}


DbContext Setup

Right now, it relies on a simple comment marker to know where to drop the new DbSet. Just add // <EFX-DBSETS> inside your context class:

using Microsoft.EntityFrameworkCore;
using App.Entities;

public class AppDbContext : DbContext
{
    public AppDbContext(DbContextOptions<AppDbContext> o
Lenguaje dominante
C#
Estrellas
14.8k
Forks
3.4k
Merge medio
3 d 18 h
PR fusionados (30 d)
159

Preparar el entorno

Abrir en Codespaces

Inicia el contenedor de desarrollo del proyecto en tu navegador, con tu propia cuenta de GitHub.

Primeros pasos

  1. Lee el issue completo y luego la guía de contribución del proyecto.
  2. Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
  3. Haz un fork del repositorio y trabaja en una rama.
  4. Abre un pull request que haga referencia al número del issue.

Más de dotnet/efcore

Todos los issues de dotnet/efcore

Issues similares

Más issues de C#

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.