21 de junio de 2026
EF Core 10: novedades y cómo dejar que un agente IA escriba migraciones seguras
Todo sobre las novedades de EF Core 10 - LeftJoin/RightJoin, filtros de query con nombre, vector search, columnas JSON - y cómo configurar Claude Code para migraciones seguras.
EF Core 10 es una versión LTS que llegó en noviembre de 2025, con soporte hasta el 10 de noviembre de 2028. Solo corre en .NET 10. Este artículo cubre qué hay de nuevo (verificado contra la página “What’s New in EF Core 10” de Microsoft Learn) y luego la pregunta práctica: ¿cómo dejas que un agente IA genere migraciones de EF Core sin romper nada?
¿Qué hay de nuevo en EF Core 10?
Operadores LINQ LeftJoin y RightJoin
EF Core 10 soporta los nuevos métodos LeftJoin y RightJoin que .NET 10 añade a LINQ. Antes de EF 10, un left outer join requería una combinación incómoda de SelectMany, GroupJoin y DefaultIfEmpty. Los nuevos operadores lo hacen directo:
var query = context.Students
.LeftJoin(
context.Departments,
student => student.DepartmentID,
department => department.ID,
(student, department) => new
{
student.FirstName,
Department = department.Name ?? "[NINGUNO]"
});
EF 10 traduce ambos operadores a LEFT JOIN y RIGHT JOIN en SQL. La sintaxis de query de C# aún no soporta estos operadores; usa sintaxis de método.
Filtros de query con nombre
Los filtros de query con nombre permiten adjuntar múltiples filtros globales a un tipo de entidad y deshabilitar individuales por query. Antes de EF 10, cada tipo de entidad soportaba solo un filtro global, y IgnoreQueryFilters() los deshabilitaba todos. Ahora:
modelBuilder.Entity<Blog>()
.HasQueryFilter("FiltroEliminacionSuave", b => !b.IsDeleted)
.HasQueryFilter("FiltroTenant", b => b.TenantId == tenantId);
// Deshabilitar solo el filtro de eliminación suave para esta query:
var todosLosBlogs = await context.Blogs
.IgnoreQueryFilters(["FiltroEliminacionSuave"])
.ToListAsync();
Esto hace que los patrones de multi-tenant + soft-delete sean significativamente más limpios.
Soporte nativo de columnas JSON (SQL Server 2025 / Azure SQL)
EF Core 10 usa automáticamente el nuevo tipo de dato json en SQL Server 2025 o Azure SQL cuando usas UseAzureSql() o configuras un nivel de compatibilidad de 170 o superior. Anteriormente, los datos JSON se almacenaban en columnas nvarchar(max). El nuevo tipo aporta mejoras de eficiencia y un mecanismo de almacenamiento más seguro. Las colecciones primitivas y tipos complejos mapeados a JSON usan el nuevo tipo automáticamente. Las columnas nvarchar(max) existentes se migran automáticamente en la siguiente migración.
EF 10 también añade soporte de ExecuteUpdateAsync para columnas JSON, permitiendo actualizaciones masivas eficientes:
await context.Blogs.ExecuteUpdateAsync(s =>
s.SetProperty(b => b.Details.Views, b => b.Details.Views + 1));
Nota: ExecuteUpdateAsync para JSON requiere mapear tus tipos como tipos complejos, no entidades owned.
Vector similarity search - fuera de preview
El vector search, introducido experimentalmente en EF 9, está listo para producción en EF 10. La función apunta a Azure SQL y SQL Server 2025. Almacenas embeddings en una columna SqlVector<float> y consultas con EF.Functions.VectorDistance():
var blogsTopSimilares = context.Blogs
.OrderBy(b => EF.Functions.VectorDistance("cosine", b.Embedding, vectorQuery))
.Take(3)
.ToListAsync();
La API de construcción de modelos también fue renombrada: usa IsVectorProperty() e IsVectorIndex(). Esta es la base para búsqueda semántica y workloads RAG directamente en SQL Server.
Tipos complejos: table splitting y mapeo JSON
EF 10 consolida los tipos complejos como el patrón recomendado para modelar value objects que se mapean a columnas adicionales (table splitting) o a una columna JSON. A diferencia de los owned entity types, los tipos complejos tienen semántica de valor: puedes asignar uno a otro y compararlos por contenido, ambas cosas que fallan con owned entities. Los tipos complejos ahora también soportan propiedades opcionales y structs de .NET.
Mejoras en la traducción de colecciones parametrizadas
EF 10 cambia la traducción predeterminada de colecciones parametrizadas (queries del estilo ids.Contains(b.Id)) para usar parámetros escalares individuales en lugar de un array JSON. Esto le da al planificador de queries información de cardinalidad mientras mantiene la forma del SQL estable entre invocaciones, reduciendo los fallos de plan cache. EF también rellena las listas de parámetros para reducir el número de formas SQL distintas.
Otros cambios notables
ExecuteUpdateAsyncahora acepta una lambda regular (no solo un árbol de expresiones), haciendo las actualizaciones masivas condicionales dramáticamente más simples de escribir.- Advertencias de inyección SQL: un nuevo analizador de Roslyn avisa cuando se usa concatenación de strings dentro de métodos SQL raw como
FromSqlRaw. - Las constantes inlineadas en SQL ahora se ocultan de los logs por defecto.
- El ordenamiento en split queries ahora es consistente, corrigiendo un caso límite de integridad de datos de larga data.
¿Cómo dejo que Claude Code genere migraciones de EF Core 10 sin romper nada?
La regla es simple: Claude Code ejecuta las herramientas dotnet ef; nunca edita manualmente los archivos generados. Así se configura esto de manera confiable.
Paso 1 - Documenta el comando exacto de migración en CLAUDE.md
En tu CLAUDE.md, incluye el comando exacto que el agente debe ejecutar cuando le pidas añadir una migración:
## Comandos de EF Core
Añadir migración: dotnet ef migrations add <Nombre> --project src/Infrastructure --startup-project src/Api
Aplicar a DB dev: dotnet ef database update --project src/Infrastructure --startup-project src/Api
Generar script SQL: dotnet ef migrations script --project src/Infrastructure --startup-project src/Api
También añade una restricción explícita:
## Reglas de EF Core
- NUNCA editar manualmente los archivos *.Designer.cs o *ModelSnapshot.cs.
Solo los comandos dotnet ef migrations escriben en esos archivos.
- Revisar los métodos Up() y Down() en cada migración generada antes de hacer commit.
Paso 2 - Pre-aprueba los comandos ef en .claude/settings.json
Sin pre-aprobación, Claude Code hará una pausa y pedirá permiso cada vez que ejecute dotnet ef. Añádelo a la lista de permitidos:
{
"permissions": {
"allow": [
"Bash(dotnet build *)",
"Bash(dotnet test *)",
"Bash(dotnet format *)",
"Bash(dotnet ef migrations add *)",
"Bash(dotnet ef database update *)",
"Bash(dotnet ef migrations script *)"
]
}
}
Este es el mismo patrón usado en el repo starter github.com/Khavel/dotnet-claude-starter.
Paso 3 - Indica al agente qué hacer después de generar la migración
En tu prompt de tarea (o en CLAUDE.md bajo “Definición de hecho”), incluye:
Después de añadir una migración: ejecuta
dotnet ef migrations scriptpara generar SQL. Inspecciona los métodos Up() y Down() y confirma que coinciden con la intención. Ejecutadotnet buildydotnet testpara confirmar que nada está roto.
El agente generará el SQL y lo incluirá en su resumen, dándote un artefacto revisable antes de que algo llegue a una base de datos real.
¿Cómo verifico una migración que escribió el agente?
Revisa los métodos Up() y Down() en el archivo de migración directamente. Este es el paso más importante. Los archivos *.Designer.cs y *ModelSnapshot.cs son generados - no necesitas leerlos. Lo que necesitas leer es la clase de migración misma:
- ¿
Up()hace exactamente lo que requiere el cambio del modelo, ni más ni menos? - ¿
Down()deshace correctamente el cambio deUp()? - Si la migración elimina una columna, ¿
Down()la vuelve a añadir con el tipo y restricciones correctos? - Para migraciones de columnas JSON en SQL Server 2025: ¿cambiará esto columnas
nvarchar(max)ajson? ¿Es eso intencional para todos los entornos?
Luego ejecuta dotnet ef migrations script e inspecciona el SQL generado. Aplícalo a una base de datos de desarrollo y verifica el esquema con tu cliente de base de datos.
FAQ
¿Cuáles son las novedades más importantes de EF Core 10?
EF Core 10 incluye operadores LINQ LeftJoin y RightJoin, filtros de query con nombre, soporte nativo de columnas JSON para SQL Server 2025/Azure SQL, vector similarity search fuera de preview, tipos complejos con table splitting y mapeo JSON, y traducción mejorada de colecciones parametrizadas.
¿Puede Claude Code generar migraciones de EF Core automáticamente?
Sí. Dale a Claude Code el comando exacto dotnet ef migrations add en CLAUDE.md, pre-apruébalo en .claude/settings.json, e instrúyele que nunca edite manualmente los archivos Designer.cs o ModelSnapshot.cs. El agente ejecuta las herramientas; las herramientas generan la migración.
¿Por qué no debo editar manualmente los archivos Designer.cs o ModelSnapshot.cs de EF Core?
Estos archivos son generados por la herramienta dotnet ef. Editarlos manualmente rompe la cadena de migraciones y puede hacer que migraciones posteriores sean incorrectas o fallen al aplicarse. La regla aplica tanto a humanos como a agentes IA.
¿Cómo verifico una migración que escribió un agente IA?
Revisa los métodos Up() y Down() en el archivo de migración. Ejecuta dotnet ef migrations script para generar el SQL. Aplícalo a una base de datos de desarrollo y verifica el esquema antes de hacer commit.
¿El dotnet-claude-starter incluye EF Core?
El starter usa almacenamiento en memoria. EF Core con PostgreSQL es lo que el kit de producción Sharpyard añade. Los patrones de CLAUDE.md y settings.json del starter son la base que llevas cuando cambias a una base de datos real.
¿Construyendo un SaaS .NET en producción, agent-first?
El starter gratuito en github.com/Khavel/dotnet-claude-starter te da la capa de operación de agente en una minimal API de .NET 10. Sharpyard es el kit de producción: .NET 10, Angular, auth, multi-tenancy, billing, EF Core + PostgreSQL, y la capa de agente completa (CLAUDE.md, config de MCP, tests de contrato, comandos pre-aprobados) integrada en todo. Únete a la lista de espera fundadora para acceso anticipado y el precio fundador.
Relacionado: Claude Code para desarrolladores .NET.
El kit completo de SaaS en .NET, nativo para agentes.
Únete a la lista de espera