Características nuevas de Entity Framework Core 3.0New features in Entity Framework Core 3.0

En la lista siguiente se incluyen las principales características nuevas de EF Core 3.0.The following list includes the major new features in EF Core 3.0.

Como versión principal, EF Core 3.0 también presenta varios cambios importantes, que son mejoras en la API que podrían afectar negativamente a las aplicaciones existentes.As a major release, EF Core 3.0 also contains several breaking changes, which are API improvements that may have negative impact on existing applications.

Revisión de LINQLINQ overhaul

LINQ permite escribir consultas a la base de datos en el lenguaje .NET que prefiera, con lo que se aprovecha la información de tipo enriquecido para ofrecer la comprobación de IntelliSense y de tipos en tiempo de compilación.LINQ enables you to write database queries using your .NET language of choice, taking advantage of rich type information to offer IntelliSense and compile-time type checking. Pero LINQ también permite escribir un número ilimitado de consultas complicadas que contienen expresiones arbitrarias (llamadas a métodos u operaciones).But LINQ also enables you to write an unlimited number of complicated queries containing arbitrary expressions (method calls or operations). Cómo controlar todas esas combinaciones es el principal desafío para los proveedores LINQ.How to handle all those combinations is the main challenge for LINQ providers.

En EF Core 3,0, hemos rediseñado nuestro proveedor LINQ para habilitar la conversión de más patrones de consulta en SQL, la generación de consultas eficientes en más casos y la prevención de que las consultas ineficaces no se detecten.In EF Core 3.0, we rearchitected our LINQ provider to enable translating more query patterns into SQL, generating efficient queries in more cases, and preventing inefficient queries from going undetected. El nuevo proveedor LINQ es la base sobre la que podremos ofrecer nuevas funcionalidades de consulta y mejoras de rendimiento en futuras versiones, sin interrumpir las aplicaciones y los proveedores de datos existentes.The new LINQ provider is the foundation over which we'll be able to offer new query capabilities and performance improvements in future releases, without breaking existing applications and data providers.

Evaluación de cliente restringidaRestricted client evaluation

El cambio de diseño más importante tiene que ver con la forma en que manejamos las expresiones LINQ que no se pueden convertir a parámetros ni traducir a SQL.The most important design change has to do with how we handle LINQ expressions that cannot be converted to parameters or translated to SQL.

En las versiones anteriores, EF Core identificada qué partes de una consulta se podían traducir a SQL y ejecutaba el resto de la consulta en el cliente.In previous versions, EF Core identified what portions of a query could be translated to SQL, and executed the rest of the query on the client. Este tipo de ejecución en el lado cliente es una opción interesante en algunas situaciones, pero en muchos otros casos puede dar lugar a consultas ineficaces.This type of client-side execution is desirable in some situations, but in many other cases it can result in inefficient queries.

Por ejemplo, si EF Core 2.2 no podía traducir un predicado en una llamada a Where(), ejecutaba una instrucción SQL sin filtro, transfería todas las filas de la base de datos y luego las filtraba en memoria:For example, if EF Core 2.2 couldn't translate a predicate in a Where() call, it executed an SQL statement without a filter, transferred all the rows from the database, and then filtered them in-memory:

var specialCustomers = context.Customers
    .Where(c => c.Name.StartsWith(n) && IsSpecialCustomer(c));

Esta operación puede ser aceptable si la base de datos contiene pocas filas, pero puede dar lugar a problemas de rendimiento considerables o incluso errores en la aplicación si la base de datos contiene muchas filas.That may be acceptable if the database contains a small number of rows but can result in significant performance issues or even application failure if the database contains a large number of rows.

En EF Core 3.0 hemos restringido la evaluación de cliente para que solo suceda en la proyección de nivel superior (fundamentalmente, la última llamada a Select()).In EF Core 3.0, we've restricted client evaluation to only happen on the top-level projection (essentially, the last call to Select()). Cuando EF Core 3.0 detecta expresiones que no se pueden traducir en ningún otro lugar de la consulta, produce una excepción en tiempo de ejecución.When EF Core 3.0 detects expressions that can't be translated anywhere else in the query, it throws a runtime exception.

Para evaluar una condición de predicado en el cliente como en el ejemplo anterior, los desarrolladores ahora tienen que cambiar explícitamente la evaluación de la consulta a LINQ to Objects:To evaluate a predicate condition on the client as in the previous example, developers now need to explicitly switch evaluation of the query to LINQ to Objects:

var specialCustomers = context.Customers
    .Where(c => c.Name.StartsWith(n))
    .AsEnumerable() // switches to LINQ to Objects
    .Where(c => IsSpecialCustomer(c));

Consulte la documentación sobre cambios importantes para más detalles sobre cómo esto puede afectar a las aplicaciones existentes.See the breaking changes documentation for more details about how this can affect existing applications.

Instrucción SQL única por consulta LINQSingle SQL statement per LINQ query

Otro aspecto del diseño que cambió significativamente en la versión 3.0 es que ahora siempre se genera una única instrucción SQL por cada consulta LINQ.Another aspect of the design that changed significantly in 3.0 is that we now always generate a single SQL statement per LINQ query. En versiones anteriores, se usaba para generar varias instrucciones SQL en ciertos casos, llamadas Include() traducidas en las propiedades de navegación de la colección y consultas traducidas que seguían determinados patrones con subconsultas.In previous versions, we used to generate multiple SQL statements in certain cases, translated Include() calls on collection navigation properties and translated queries that followed certain patterns with subqueries. Aunque en ocasiones este diseño resultaba práctico y, en el caso de Include(), incluso ayudaba a evitar el envío de datos redundantes a través de la conexión, la implementación era compleja y se producían algunos comportamientos considerablemente ineficaces (consultas N+1).Although this was in some cases convenient, and for Include() it even helped avoid sending redundant data over the wire, the implementation was complex, and it resulted in some extremely inefficient behaviors (N+1 queries). Había situaciones en las que los datos devueltos en varias consultas eran incoherentes en potencia.There were situations in which the data returned across multiple queries was potentially inconsistent.

De forma similar a la evaluación del cliente, si EF Core 3.0 no puede convertir una consulta LINQ en una única instrucción SQL, se inicia una excepción en tiempo de ejecución.Similarly to client evaluation, if EF Core 3.0 can't translate a LINQ query into a single SQL statement, it throws a runtime exception. Pero hicimos que EF Core fuera capaz de traducir muchos de los patrones comunes que solían generar varias consultas en una sola consulta con JOIN.But we made EF Core capable of translating many of the common patterns that used to generate multiple queries to a single query with JOINs.

Compatibilidad con Cosmos DBCosmos DB support

Con el proveedor de Cosmos DB para EF Core, los desarrolladores que están familiarizados con el modelo de programación de EF puedan usar fácilmente Azure Cosmos DB como base de datos de aplicación.The Cosmos DB provider for EF Core enables developers familiar with the EF programing model to easily target Azure Cosmos DB as an application database. El objetivo es hacer que algunas de las ventajas de Cosmos DB, como la distribución global, la disponibilidad "AlwaysOn", la escalabilidad elástica y la baja latencia, sean aún más accesibles para los desarrolladores de .NET.The goal is to make some of the advantages of Cosmos DB, like global distribution, "always on" availability, elastic scalability, and low latency, even more accessible to .NET developers. El proveedor habilita la mayoría de las características de EF Core, como el seguimiento automático de cambios, LINQ y conversiones de valores, en comparación con SQL API de Cosmos DB.The provider enables most EF Core features, like automatic change tracking, LINQ, and value conversions, against the SQL API in Cosmos DB.

Consulte la documentación del proveedor Cosmos DB para más detalles.See the Cosmos DB provider documentation for more details.

Compatibilidad con C# 8.0C# 8.0 support

EF Core 3.0 aprovecha varias características nuevas de C# 8.0:EF Core 3.0 takes advantage of a couple of the new features in C# 8.0:

Secuencias asincrónicasAsynchronous streams

Los resultados de la consulta asincrónica se exponen ahora mediante la nueva interfaz de await foreach estándar y se pueden usar con IAsyncEnumerable<T>.Asynchronous query results are now exposed using the new standard IAsyncEnumerable<T> interface and can be consumed using await foreach.

var orders =
    from o in context.Orders
    where o.Status == OrderStatus.Pending
    select o;

await foreach(var o in orders.AsAsyncEnumerable())
{
    Process(o);
}

Consulte las transmisiones asíncronas en la documentación de C# para más detalles.See the asynchronous streams in the C# documentation for more details.

Tipos de referencia que aceptan valores NULLNullable reference types

Cuando esta nueva característica está habilitada en el código, EF Core examina la nulabilidad de las propiedades de tipo de referencia y la aplica a las columnas y relaciones correspondientes en la base de datos: las propiedades de los tipos de referencia no anulables se tratan como si tuvieran el atributo de anotación de datos [Required].When this new feature is enabled in your code, EF Core examines the nullability of reference type properties and applies it to corresponding columns and relationships in the database: properties of non-nullable references types are treated as if they had the [Required] data annotation attribute.

Por ejemplo, en la clase siguiente, las propiedades marcadas como de tipo string? se configurarán como opcionales, mientras que string se configurará según sea necesario:For example, in the following class, properties marked as of type string? will be configured as optional, whereas string will be configured as required:

public class Customer
{
    public int Id { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string? MiddleName { get; set; }
}

Consulte Trabajar con tipos de referencia que aceptan valores NULL en la documentación de EF Core para más detalles.See Working with nullable reference types in the EF Core documentation for more details.

Intercepción de operaciones de bases de datosInterception of database operations

La nueva API de intercepción en EF Core 3.0 permite proporcionar una lógica personalizada que se invoca automáticamente cada vez que se producen operaciones de base de datos de bajo nivel como parte del funcionamiento normal de EF Core.The new interception API in EF Core 3.0 allows providing custom logic to be invoked automatically whenever low-level database operations occur as part of the normal operation of EF Core. Por ejemplo, al abrir conexiones, confirmar transacciones o ejecutar comandos.For example, when opening connections, committing transactions, or executing commands.

De manera similar a las características de intercepción que existían en EF 6, los interceptores le permiten interceptar operaciones antes o después de que sucedan.Similarly to the interception features that existed in EF 6, interceptors allow you to intercept operations before or after they happen. Cuando las intercepta antes de que sucedan, puede omitir la ejecución y proporcionar resultados alternativos de la lógica de intercepción.When you intercept them before they happen, you are allowed to by-pass execution and supply alternate results from the interception logic.

Por ejemplo, para manipular el texto del comando, puede crear IDbCommandInterceptor:For example, to manipulate command text, you can create an IDbCommandInterceptor:

public class HintCommandInterceptor : DbCommandInterceptor
{
    public override InterceptionResult ReaderExecuting(
        DbCommand command,
        CommandEventData eventData,
        InterceptionResult result)
    {
        // Manipulate the command text, etc. here...
        command.CommandText += " OPTION (OPTIMIZE FOR UNKNOWN)";
        return result;
    }
}

Y registrarlo con su  DbContext:And register it with your DbContext:

services.AddDbContext(b => b
    .UseSqlServer(connectionString)
    .AddInterceptors(new HintCommandInterceptor()));

Ingeniería inversa de vistas de base de datosReverse engineering of database views

El nombre de los tipos de consulta, que representan datos que pueden leerse de la base de datos pero no actualizarse, se ha cambiado a tipos de entidad sin clave.Query types, which represent data that can be read from the database but not updated, have been renamed to keyless entity types. Como son una excelente opción para asignar vistas de bases de datos en la mayoría de los escenarios, EF Core ahora crea automáticamente tipos de entidades sin clave cuando se invierten las vistas de bases de datos de ingeniería.As they are an excellent fit for mapping database views in most scenarios, EF Core now automatically creates keyless entity types when reverse engineering database views.

Por ejemplo, con la herramienta de línea de comandos dotnet ef, puede escribir:For example, using the dotnet ef command-line tool you can type:

dotnet ef dbcontext scaffold "Server=(localdb)\mssqllocaldb;Database=Blogging;Trusted_Connection=True;" Microsoft.EntityFrameworkCore.SqlServer

Y la herramienta ahora anulará automáticamente los tipos de scaffold para vistas y tablas sin claves:And the tool will now automatically scaffold types for views and tables without keys:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Names>(entity =>
    {
        entity.HasNoKey();
        entity.ToView("Names");
    });

    modelBuilder.Entity<Things>(entity =>
    {
        entity.HasNoKey();
    });
}

Ahora, las entidades dependientes que comparten la tabla con la entidad de seguridad son opcionalesDependent entities sharing the table with the principal are now optional

A partir de la versión EF Core 3.0, si OrderDetails pertenece a Order o está asignado a la misma tabla explícitamente, será posible agregar Order sin OrderDetails; todas las propiedades OrderDetails, salvo la clave principal, se asignarán a columnas que aceptan valores NULL.Starting with EF Core 3.0, if OrderDetails is owned by Order or explicitly mapped to the same table, it will be possible to add an Order without an OrderDetails and all of the OrderDetails properties, except the primary key will be mapped to nullable columns.

Al realizar consultas, EF Core establecerá OrderDetails en null si ninguna de las propiedades necesarias tiene un valor, o bien no tiene las propiedades necesarias más allá de la clave principal y todas las propiedades son null.When querying, EF Core will set OrderDetails to null if any of its required properties doesn't have a value, or if it has no required properties besides the primary key and all properties are null.

public class Order
{
    public int Id { get; set; }
    public int CustomerId { get; set; }
    public OrderDetails Details { get; set; }
}

[Owned]
public class OrderDetails
{
    public int Id { get; set; }
    public string ShippingAddress { get; set; }
}

EF 6.3 en .NET CoreEF 6.3 on .NET Core

Esta no es realmente una característica de EF Core 3.0, pero creemos que es importante para muchos de nuestros clientes actuales.This isn't really an EF Core 3.0 feature, but we think it is important to many of our current customers.

Entendemos que muchas aplicaciones existentes utilizan versiones anteriores de EF y que portarlas a EF Core solo para aprovechar las ventajas de .NET Core puede requerir un esfuerzo considerable.We understand that many existing applications use previous versions of EF, and that porting them to EF Core only to take advantage of .NET Core can require a significant effort. Por ese motivo, decidimos portar a la versión más reciente de EF 6 para que se ejecute en .NET Core 3.0.For that reason, we decided to port the newest version of EF 6 to run on .NET Core 3.0.

Para más detalles, consulte Novedades de EF 6.For more details, see what's new in EF 6.

Características pospuestasPostponed features

Algunas características planeadas originalmente para EF Core 3.0 se pospusieron para versiones futuras:Some features originally planned for EF Core 3.0 were postponed to future releases:

  • Capacidad de omitir partes de un modelo en migraciones, con seguimiento realizado a través del problema nº 2725.Ability to ignore parts of a model in migrations, tracked as #2725.
  • Entidades contenedoras de propiedades, de las que se realiza un seguimiento a través de dos problemas independientes: nº 9914 sobre las entidades de tipo compartido y nº 13610 sobre la compatibilidad con la asignación de propiedades indizadas.Property bag entities, tracked as two separate issues: #9914 about shared-type entities and #13610 about indexed property mapping support.