Tipos de entidad sin llave

Nota

Esta característica se agregó bajo el nombre de los tipos de consulta. Más adelante se cambió el nombre a tipos de entidad sin clave. La [Keyless] anotación de datos empezó a estar disponible en EFCore 5.0.

Además de los tipos de entidad normales, un modelo de EF Core puede contener tipos de entidad sin clave ,que se pueden usar para llevar a cabo consultas de base de datos en datos que no contienen valores de clave.

Definición de tipos de entidad sin clave

Los tipos de entidad sin clave se pueden definir mediante la anotación de datos o Fluent API:

[Keyless]
public class BlogPostsCount
{
    public string BlogName { get; set; }
    public int PostCount { get; set; }
}

Características de los tipos de entidad sin clave

Los tipos de entidad sin clave admiten muchas de las mismas funcionalidades de asignación que los tipos de entidad normales, como la asignación de herencia y las propiedades de navegación. En los almacenes relacionales, pueden configurar los objetos y columnas de la base de datos de destino a través de métodos de API fluidas o anotaciones de datos.

Sin embargo, son diferentes de los tipos de entidad normales en que:

  • No se puede definir una clave.
  • Nunca se realiza un seguimiento de los cambios en DbContext y, por tanto, nunca se insertan, actualizan ni eliminan en la base de datos.
  • Nunca se detectan por convención.
  • Solo admite un subconjunto de funcionalidades de asignación de navegación, específicamente:
    • Es posible que nunca actúen como el final principal de una relación.
    • Es posible que no tengan navegaciones a entidades propias
    • Solo pueden contener propiedades de navegación de referencia que apunten a entidades normales.
    • Las entidades no pueden contener propiedades de navegación para tipos de entidad sin clave.
  • Debe configurarse con una [Keyless] anotación de datos o una llamada .HasNoKey() de método.
  • Se puede asignar a una consulta de definición. Una consulta de definición es una consulta declarada en el modelo que actúa como origen de datos para un tipo de entidad sin clave.

Escenarios de uso

Algunos de los escenarios de uso principales para los tipos de entidad sin clave son:

  • Que sirve como tipo de valor devuelto para consultas SQL sin formato.
  • Asignación a vistas de base de datos que no contienen una clave principal.
  • Asignación a tablas que no tienen definida una clave principal.
  • Asignación a consultas definidas en el modelo.

Asignación a objetos de base de datos

La asignación de un tipo de entidad sin clave a un objeto de base de datos se logra mediante ToTable la API fluida o ToView . Desde la perspectiva de EF Core, el objeto de base de datos especificado en este método es una vista ,lo que significa que se trata como un origen de consulta de solo lectura y no puede ser el destino de las operaciones de actualización, inserción o eliminación. Sin embargo, esto no significa que el objeto de base de datos sea realmente necesario para ser una vista de base de datos. También puede ser una tabla de base de datos que se tratará como de solo lectura. Por el contrario, para los tipos de entidad normales, EF Core supone que un objeto de base de datos especificado en el método se puede tratar como una tabla , lo que significa que se puede usar como origen de consulta, pero también como destino de las operaciones de actualización, eliminación ToTable e inserción. ToTable De hecho, puede especificar el nombre de una vista de base de datos en y todo debería funcionar bien siempre que la vista esté configurada para ser actualizable en la base ToTable de datos.

Nota

Hasta EF Core 5.0 presupone que el objeto ya existe en la base de datos y no lo crearán ToView las migraciones. En EF Core 5.0 y versiones posteriores para excluir el objeto de las migraciones, vea modelBuilder.Entity<ViewType>().ToTable("ViewNameInDatabase", t => t.ExcludeFromMigrations())modelBuilder.Entity<ViewType>().ToTable("ViewNameInDatabase", t => t.ExcludeFromMigrations())trata de forma diferente mediante migraciones .

Ejemplo

En el ejemplo siguiente se muestra cómo usar tipos de entidad sin clave para consultar una vista de base de datos.

Sugerencia

Puede ver un ejemplo de este artículo en GitHub.

En primer lugar, definimos un modelo simple de blog y publicación:

public class Blog
{
    public int BlogId { get; set; }
    public string Name { get; set; }
    public string Url { get; set; }
    public ICollection<Post> Posts { get; set; }
}

public class Post
{
    public int PostId { get; set; }
    public string Title { get; set; }
    public string Content { get; set; }
    public int BlogId { get; set; }
}

A continuación, definimos una vista de base de datos simple que nos permitirá consultar el número de publicaciones asociadas a cada blog:

db.Database.ExecuteSqlRaw(
    @"CREATE VIEW View_BlogPostCounts AS
        SELECT b.Name, Count(p.PostId) as PostCount
        FROM Blogs b
        JOIN Posts p on p.BlogId = b.BlogId
        GROUP BY b.Name");

A continuación, definimos una clase para contener el resultado de la vista de base de datos:

public class BlogPostsCount
{
    public string BlogName { get; set; }
    public int PostCount { get; set; }
}

A continuación, configuramos el tipo de entidad sin clave en OnModelCreating mediante la API. Usamos la API de configuración fluida para configurar la asignación para el tipo de entidad sin clave:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder
        .Entity<BlogPostsCount>(
            eb =>
            {
                eb.HasNoKey();
                eb.ToView("View_BlogPostCounts");
                eb.Property(v => v.BlogName).HasColumnName("Name");
            });
}

A continuación, configuramos DbContext para incluir DbSet<T> :

public DbSet<BlogPostsCount> BlogPostCounts { get; set; }

Por último, podemos consultar la vista de base de datos de la manera estándar:

var postCounts = db.BlogPostCounts.ToList();

foreach (var postCount in postCounts)
{
    Console.WriteLine($"{postCount.BlogName} has {postCount.PostCount} posts.");
    Console.WriteLine();
}

Sugerencia

Tenga en cuenta que también hemos definido una propiedad de consulta de nivel de contexto (DbSet) para que actúe como raíz para las consultas en este tipo.

Sugerencia

Para probar los tipos de entidad sin clave asignados a vistas mediante el proveedor en memoria, debe asignarlos a una consulta a través de ToInMemoryQuery . Consulte un ejemplo que se puede ejecutar mediante esta técnica para obtener más detalles.