Anotaciones de Datos en Code First: Índices y Relaciones

using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace EjemploIndices
{
    public class Entrada
    {
        public int Identificador { get; set; }
        public string Titulo { get; set; }

        [Index("IndiceCalificacion")]
        public int BlogId { get; set; }
    }

    public class Usuario
    {
        public int UserId { get; set; }

        [Index(IsUnique = true)]
        [StringLength(200)]
        public string NombreUsuario { get; set; }

        public string NombreVisible { get; set; }
    }

    public class Celda
    {
        public int Id { get; set; }
        public string Contenido { get; set; }

        [Index("IX_Posicion", 1, IsUnique = true)]
        public int Fila { get; set; }

        [Index("IX_Posicion", 2)]
        [StringLength(5)]
        public string Columna { get; set; }
    }
}

La generación de la base de datos produce el siguiente esquema SQL:

CREATE TABLE [dbo].[Entradas] (
    [Identificador] INT            IDENTITY (1, 1) NOT NULL,
    [Titulo]        NVARCHAR (MAX) NULL,
    [BlogId]        INT            NOT NULL,
    CONSTRAINT [PK_dbo.Entradas] PRIMARY KEY CLUSTERED ([Identificador] ASC)
);
GO
CREATE NONCLUSTERED INDEX [IndiceCalificacion] ON [dbo].[Entradas]([BlogId] ASC);
GO

CREATE TABLE [dbo].[Usuarios] (
    [UserId]        INT            IDENTITY (1, 1) NOT NULL,
    [NombreUsuario] NVARCHAR (200) NULL,
    [NombreVisible] NVARCHAR (MAX) NULL,
    CONSTRAINT [PK_dbo.Usuarios] PRIMARY KEY CLUSTERED ([UserId] ASC)
);
GO
CREATE UNIQUE NONCLUSTERED INDEX [IX_NombreUsuario]
    ON [dbo].[Usuarios]([NombreUsuario] ASC);
GO

CREATE TABLE [dbo].[Celdas] (
    [Id]        INT            IDENTITY (1, 1) NOT NULL,
    [Contenido] NVARCHAR (MAX) NULL,
    [Fila]      INT            NOT NULL,
    [Columna]   NVARCHAR (5)   NULL,
    CONSTRAINT [PK_dbo.Celdas] PRIMARY KEY CLUSTERED ([Id] ASC)
);
GO
CREATE UNIQUE NONCLUSTERED INDEX [IX_Posicion]
    ON [dbo].[Celdas]([Fila] ASC, [Columna] ASC);
GO
  • La clase Entrada crea un índice llamado IndiceCalificacion en la propiedad BlogId.
  • En la clase Usuario, se define un índice único sin nombre explícito; el framework genera uno con el formato IX_NombrePropiedad.
  • La clase Celda utiliza un índice compuesto en Fila y Columna. Las opciones del índice, como la unicidad, se aplican en la primera propiedad del grupo.
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace EjemploForaneas
{
    public class BlogPrincipal
    {
        [Key]
        public int ClavePrimaria { get; set; }
        public string Titulo { get; set; }

        public virtual ICollection<entradapublicacion> Publicaciones { get; set; }
    }

    public class EntradaPublicacion
    {
        public int Id { get; set; }
        public string Texto { get; set; }
        public int BlogPrincipalId { get; set; }

        [ForeignKey("BlogPrincipalId")]
        public BlogPrincipal BlogPrincipal { get; set; }
    }
}</entradapublicacion>

La tabla generada incluye una restricción de clave foránea e índice:

CREATE TABLE [dbo].[BlogPrincipal] (
    [ClavePrimaria] INT            IDENTITY (1, 1) NOT NULL,
    [Titulo]        NVARCHAR (MAX) NULL,
    CONSTRAINT [PK_dbo.BlogPrincipal] PRIMARY KEY CLUSTERED ([ClavePrimaria] ASC)
);

CREATE TABLE [dbo].[EntradaPublicacion] (
    [Id]               INT            IDENTITY (1, 1) NOT NULL,
    [Texto]            NVARCHAR (MAX) NULL,
    [BlogPrincipalId]  INT            NOT NULL,
    CONSTRAINT [PK_dbo.EntradaPublicacion] PRIMARY KEY CLUSTERED ([Id] ASC),
    CONSTRAINT [FK_dbo.EntradaPublicacion_dbo.BlogPrincipal_BlogPrincipalId]
        FOREIGN KEY ([BlogPrincipalId]) REFERENCES [dbo].[BlogPrincipal] ([ClavePrimaria])
        ON DELETE CASCADE
);
GO
CREATE NONCLUSTERED INDEX [IX_BlogPrincipalId]
    ON [dbo].[EntradaPublicacion]([BlogPrincipalId] ASC);

La anotación [ForeignKey] puede aplicarse tanto a la propiedad de naveagción como a la propiedad de clave foránea. El resultado en el esquema de la base de datos es idéntico en ambos casos, ya que establece la correspondencia entre los atributos.

using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;

namespace EjemploInverso
{
    public class Persona
    {
        public int Id { get; set; }

        [Index(IsUnique = true)]
        [StringLength(50)]
        public string Nombre { get; set; }

        [InverseProperty("CreadoPor")]
        public List<document> DocumentosCreados { get; set; }

        [InverseProperty("ActualizadoPor")]
        public List<document> DocumentosActualizados { get; set; }
    }

    public class Document
    {
        public int Id { get; set; }
        public string Contenido { get; set; }

        public Persona CreadoPor { get; set; }
        public Persona ActualizadoPor { get; set; }
    }
}</document></document>

El esquema de la base de datos resultante crea las claves foráneas necesarias y sus respectivos índices:

CREATE TABLE [dbo].[Persona] (
    [Id]     INT           IDENTITY (1, 1) NOT NULL,
    [Nombre] NVARCHAR (50) NULL,
    CONSTRAINT [PK_dbo.Persona] PRIMARY KEY CLUSTERED ([Id] ASC)
);
GO
CREATE UNIQUE NONCLUSTERED INDEX [IX_Nombre]
    ON [dbo].[Persona]([Nombre] ASC);

CREATE TABLE [dbo].[Document] (
    [Id]               INT            IDENTITY (1, 1) NOT NULL,
    [Contenido]        NVARCHAR (MAX) NULL,
    [CreadoPor_Id]     INT            NULL,
    [ActualizadoPor_Id] INT            NULL,
    CONSTRAINT [PK_dbo.Document] PRIMARY KEY CLUSTERED ([Id] ASC),
    CONSTRAINT [FK_dbo.Document_dbo.Persona_CreadoPor_Id]
        FOREIGN KEY ([CreadoPor_Id]) REFERENCES [dbo].[Persona] ([Id]),
    CONSTRAINT [FK_dbo.Document_dbo.Persona_ActualizadoPor_Id]
        FOREIGN KEY ([ActualizadoPor_Id]) REFERENCES [dbo].[Persona] ([Id])
);
GO
CREATE NONCLUSTERED INDEX [IX_CreadoPor_Id]
    ON [dbo].[Document]([CreadoPor_Id] ASC);
GO
CREATE NONCLUSTERED INDEX [IX_ActualizadoPor_Id]
    ON [dbo].[Document]([ActualizadoPor_Id] ASC);

Entity Fraemwork nombra automáticamente las columnas de clave toánea en la tabla dependiente como NombrePropiedadNavegación_Id.

Etiquetas: Entity Framework Data Annotations Code First SQL Server Índices

Publicado el 5-31 22:01