Nuevas características de EF Core 2.1
Además de numerosas correcciones de errores y pequeñas mejoras funcionales y de rendimiento, EF Core 2.1 incluye algunas características nuevas atractivas:
Carga diferida
EF Core ahora contiene los bloques de creación necesarios para que cualquier usuario cree clases de entidad que puedan cargar sus propiedades de navegación a petición. También hemos creado un nuevo paquete, Microsoft.EntityFrameworkCore.Proxies, que aprovecha esos bloques de creación para generar clases de proxy de carga diferida basadas en clases de entidad modificadas mínimamente (por ejemplo, clases con propiedades de navegación virtual).
Lea la sección sobre la carga diferida para obtener más información sobre este tema.
Parámetros en constructores de entidad
Como uno de los bloques de creación necesarios para la carga diferida, se habilita la creación de entidades que aceptan parámetros en sus constructores. Puede usar parámetros para insertar valores de propiedad, delegados de carga diferida y servicios.
Lea la sección sobre el constructor de entidades con parámetros para obtener más información sobre este tema.
Conversiones de valor
Hasta ahora, EF Core solo podía asignar propiedades de tipos de forma nativa compatibles con el proveedor de base de datos subyacente. Los valores se copiaron entre columnas y propiedades sin ninguna transformación. A partir de EF Core 2.1, las conversiones de valores se pueden aplicar para transformar los valores obtenidos de las columnas antes de que se apliquen a las propiedades y viceversa. Tenemos una serie de conversiones que se pueden aplicar por convención según sea necesario, así como una API de configuración explícita que permite registrar conversiones personalizadas entre columnas y propiedades. Algunas de las aplicaciones de esta característica son:
- Almacenar enumeraciones como cadenas
- El mapeo de enteros sin signo con SQL Server
- Cifrado y descifrado automáticos de valores de propiedad
Lea la sección sobre las conversiones de valores para obtener más información sobre este tema.
Traducción de LINQ GroupBy
Antes de la versión 2.1, en EF Core, el operador GroupBy LINQ siempre se evaluaría en memoria. Ahora se admite la traducción a la cláusula SQL GROUP BY en los casos más comunes.
En este ejemplo se muestra una consulta con GroupBy que se usa para calcular varias funciones de agregado:
var query = context.Orders
.GroupBy(o => new { o.CustomerId, o.EmployeeId })
.Select(g => new
{
g.Key.CustomerId,
g.Key.EmployeeId,
Sum = g.Sum(o => o.Amount),
Min = g.Min(o => o.Amount),
Max = g.Max(o => o.Amount),
Avg = g.Average(o => o.Amount)
});
La traducción sql correspondiente tiene este aspecto:
SELECT [o].[CustomerId], [o].[EmployeeId],
SUM([o].[Amount]), MIN([o].[Amount]), MAX([o].[Amount]), AVG([o].[Amount])
FROM [Orders] AS [o]
GROUP BY [o].[CustomerId], [o].[EmployeeId];
Propagación de datos
Con la nueva versión, será posible proporcionar datos iniciales para rellenar una base de datos. A diferencia de en EF6, los datos de inicialización están asociados a un tipo de entidad como parte de la configuración del modelo. Después, las migraciones de EF Core pueden calcular automáticamente qué operaciones de inserción, actualización o eliminación deben aplicarse al actualizar la base de datos a una nueva versión del modelo.
Por ejemplo, esto se puede usar para configurar los datos de inicialización de un método POST en OnModelCreating
:
modelBuilder.Entity<Post>().HasData(new Post{ Id = 1, Text = "Hello World!" });
Lea la sección sobre la propagación de datos para obtener más información sobre este tema.
Tipos de consulta
Un modelo de EF Core ahora puede incluir tipos de consulta. A diferencia de los tipos de entidad, los tipos de consulta no tienen claves definidas en ellas y no se pueden insertar, eliminar ni actualizar (es decir, son de solo lectura), pero las consultas pueden devolverlas directamente. Algunos de los escenarios de uso para los tipos de consulta son:
- Asignar a vistas sin claves principales
- Asignar a tablas sin claves principales
- Asignar a consultas definidas en el modelo
- Actuar como tipo de valor devuelto en consultas
FromSql()
Lea la sección sobre los tipos de consulta para obtener más información sobre este tema.
Include en tipos derivados
Ahora será posible especificar propiedades de navegación definidas solo en tipos derivados al escribir expresiones para el método Include
. Para la versión fuertemente tipada de Include
, se admite el uso de una conversión explícita o el operador as
. Ahora también se admite hacer referencia a los nombres de propiedad de navegación definidos en tipos derivados en la versión de cadena de Include
:
var option1 = context.People.Include(p => ((Student)p).School);
var option2 = context.People.Include(p => (p as Student).School);
var option3 = context.People.Include("School");
Lea la sección sobre la inclusión de tipos derivados para obtener más información sobre este tema.
Compatibilidad con System.Transactions
Hemos agregado la capacidad de trabajar con características de System.Transactions, como TransactionScope. Esto funcionará en .NET Framework y .NET Core cuando se usen proveedores de bases de datos que lo admitan.
Lea la sección de System.Transactions para obtener más información sobre este tema.
Mejor ordenación de columnas en la migración inicial
En función de los comentarios de los clientes, hemos actualizado las migraciones para generar inicialmente columnas para tablas en el mismo orden que las propiedades se declaran en las clases. Tenga en cuenta que EF Core no puede cambiar el orden cuando se agregan nuevos miembros después de la creación de la tabla inicial.
Optimización de subconsultas correlacionadas
Hemos mejorado la traducción de consultas para evitar ejecutar consultas SQL "N + 1" en muchos escenarios comunes en los que el uso de una propiedad de navegación en la proyección conduce a unir datos de la consulta raíz con datos de una subconsulta correlacionada. La optimización requiere almacenar en búfer los resultados de la subconsulta, y es necesario modificar la consulta para adoptar el nuevo comportamiento.
Por ejemplo, la siguiente consulta normalmente se traduce en una consulta para Clientes, más N consultas independientes para Pedidos, donde "N" es el número de clientes devueltos.
var query = context.Customers.Select(
c => c.Orders.Where(o => o.Amount > 100).Select(o => o.Amount));
Al incluir ToListAsync()
en el lugar correcto, se indica que el almacenamiento en búfer es adecuado para los pedidos, lo que permite la optimización:
var query = context.Customers.Select(
c => c.Orders.Where(o => o.Amount > 100).Select(o => o.Amount).ToList());
Tenga en cuenta que esta consulta se traducirá solo a dos consultas SQL: una para clientes y la siguiente para Pedidos.
Atributo [Owned]
Ahora es posible configurar tipos de entidad en propiedad anotando simplemente el tipo con [Owned]
y asegurándose luego de que la entidad de propietario se agrega al modelo:
[Owned]
public class StreetAddress
{
public string Street { get; set; }
public string City { get; set; }
}
public class Order
{
public int Id { get; set; }
public StreetAddress ShippingAddress { get; set; }
}
Herramienta de línea de comandos dotnet-ef incluida en el SDK de .NET Core
Los comandos dotnet-ef ahora forman parte del SDK de .NET Core, por lo que ya no será necesario usar DotNetCliToolReference en el proyecto para poder usar migraciones o aplicar scaffolding a DbContext desde una base de datos existente.
Consulte la sección sobre instalar las herramientas para obtener más información sobre cómo habilitar las herramientas de línea de comandos para diferentes versiones del SDK de .NET Core y EF Core.
Paquete Microsoft.EntityFrameworkCore.Abstractions
El nuevo paquete contiene atributos e interfaces que puede usar en los proyectos para iluminar las características de EF Core sin depender de EF Core en su conjunto. Por ejemplo, el atributo [Propiedad] y la interfaz ILazyLoader se encuentran aquí.
Eventos de cambio de estado
Se pueden usar nuevos eventos de Tracked
y StateChanged
en ChangeTracker
para escribir lógica que reacciona a las entidades que entran en DbContext o cambian su estado.
Analizador de parámetros SQL en bruto
Se incluye un nuevo analizador de código con EF Core que detecta usos potencialmente no seguros de nuestras API raw-SQL, como FromSql
o ExecuteSqlCommand
. Por ejemplo, para la consulta siguiente, verá una advertencia porque minAge no está parametrizado:
var sql = $"SELECT * FROM People WHERE Age > {minAge}";
var query = context.People.FromSql(sql);
Compatibilidad del proveedor de bases de datos
Se recomienda usar EF Core 2.1 con proveedores que hayan sido actualizados o que al menos hayan sido probados para funcionar con EF Core 2.1.
Sugerencia
Si encuentra alguna incompatibilidad inesperada o cualquier problema en las nuevas características, o si tiene comentarios sobre ellas, infórmelo utilizando nuestro sistema de seguimiento.