efx new Product: One Command to Scaffold EF Core & Apply Migrations
I maintainer di solito rispondono entro 2 giorni
Nessuno ha ancora preso questa issue.
Valutazione
- Difficoltà
- 5/5
- Tempo stimato
- Più di una settimana
- Idoneità per principianti
- 35/100
- Tipo di issue
- Funzionalità
- Chiarezza
- Abbastanza chiara
- Stato di attività
- Attiva
- Stack tecnologico
- csharp
- Ambito
- cli, developer-experience
Direzione di ricerca
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.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Descrizione
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:
- Create a new
.csfile in theEntitiesfolder. - Add the class and a primary key.
- Open
DbContextand wire up a newDbSet<T>. - Run
dotnet ef migrations add ... - 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 generatesProduct.cswith a defaultId. - Locates
AppDbContext.csand injectspublic DbSet<Product> Products => Set<Product>();. - Shells out to
dotnet ef migrations add AddProduct. - Runs
dotnet ef database updateimmediately 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
- Lingua principale
- C#
- Stelle
- 14.8k
- Fork
- 3.4k
- Merge medio
- 3g 18h
- PR unite (30g)
- 159
Preparare l'ambiente
Avvia il container di sviluppo del progetto nel browser, con il tuo account GitHub.
- Nessun Dockerfile né file Docker Compose
- Ha un modello di pull request
- Leggi la guida per i contributori
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Altre issue di dotnet/efcore
-
customer-reported
Difficoltà 4/5 3-5 giorni Idoneità per principianti 54/100
I maintainer di solito rispondono entro 2 giorni
-
Difficoltà 4/5 3-5 giorni Idoneità per principianti 48/100
I maintainer di solito rispondono entro 2 giorni
-
Difficoltà 4/5 3-5 giorni Idoneità per principianti 48/100
I maintainer di solito rispondono entro 2 giorni
-
Regression in 11.0: replacing an owned instance or re-adding an entity with the same key sets unchanged OnAdd properties to nullForse già presa @seragAhmed l’ha presa oggi. Aperta
Difficoltà 4/5 3-5 giorni Idoneità per principianti 48/100
dotnet/efcore#39617 · 1 commento ·
I maintainer di solito rispondono entro 2 giorni
-
customer-reported
Difficoltà 4/5 3-5 giorni Idoneità per principianti 48/100
I maintainer di solito rispondono entro 2 giorni
Tutte le issue di dotnet/efcore
Issue simili
-
bug emitter:client:csharp
Difficoltà 2/5 1-3 ore Idoneità per principianti 84/100
microsoft/typespec#12572 · 1 commento · 1 reazione ·
I maintainer di solito rispondono entro 1 giorno
-
needs-area-label
Difficoltà 2/5 1-3 ore Idoneità per principianti 78/100
I maintainer di solito rispondono entro 2 giorni
-
AWS Lambda: KeyNotFoundException drops HTTP-triggered transactions when allowAllHeaders is disabledApertabug
Difficoltà 2/5 1-3 ore Idoneità per principianti 70/100
newrelic/newrelic-dotnet-agent#3949 · 1 commento ·
I maintainer di solito rispondono entro 1 giorno
-
area-networking
Difficoltà 2/5 1-3 ore Idoneità per principianti 78/100
dotnet/aspnetcore#70545 · 1 commento ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 87/100
I maintainer di solito rispondono entro 1 giorno