Buscar..


Observaciones

Entity Framework Code-First proporciona un conjunto de atributos de Anotación de Datos, que puede aplicar a sus clases y propiedades de dominio. Los atributos de DataAnnotation anulan las convenciones predeterminadas de código primero.

  1. System.ComponentModel.DataAnnotations incluye atributos que afectan la capacidad de nulos o el tamaño de la columna.
  2. System.ComponentModel.DataAnnotations.Schema namespace incluye atributos que afectan el esquema de la base de datos.

Nota: las Anotaciones de datos solo le brindan un subconjunto de opciones de configuración. Fluent API proporciona un conjunto completo de opciones de configuración disponibles en Code-First.

Atributo [clave]

La clave es un campo en una tabla que identifica de forma única cada fila / registro en una tabla de base de datos.

Utilice este atributo para anular la convención predeterminada de Code-First . Si se aplica a una propiedad, se usará como la columna de clave principal para esta clase.

using System.ComponentModel.DataAnnotations;

public class Person
{
    [Key]
    public int PersonKey { get; set; }        // <- will be used as primary key
     
    public string PersonName { get; set; }    
}

Si se requiere una clave primaria compuesta, el atributo [Clave] también se puede agregar a varias propiedades. El orden de las columnas dentro de la clave compuesta debe proporcionarse en el formulario [ Clave, Columna (Orden = x)] .

using System.ComponentModel.DataAnnotations;

public class Person
{
    [Key, Column(Order = 0)]
    public int PersonKey1 { get; set; }    // <- will be used as part of the primary key

    [Key, Column(Order = 1)]
    public int PersonKey2 { get; set; }    // <- will be used as part of the primary key
     
    public string PersonName { get; set; }    
}

Sin el atributo [Clave] , EntityFramework volverá a la convención predeterminada, que consiste en utilizar la propiedad de la clase como clave principal que se denomina "Id" o "{ClassName} Id".

public class Person
{
    public int PersonID { get; set; }        // <- will be used as primary key
     
    public string PersonName { get; set; }    
}

[Requerido] atributo

Cuando se aplica a una propiedad de una clase de dominio, la base de datos creará una columna NOT NULL.

using System.ComponentModel.DataAnnotations;

public class Person
{
    public int PersonID { get; set; }
    
    [Required]
    public string PersonName { get; set; }    
}

La columna resultante con la restricción NOT NULL:

La columna resultante en un servidor SQL

Nota: También se puede usar con asp.net-mvc como un atributo de validación.

Atributos [MaxLength] y [MinLength]

El atributo [MaxLength (int)] se puede aplicar a una cadena o propiedad de tipo de matriz de una clase de dominio. Entity Framework establecerá el tamaño de una columna al valor especificado.

using System.ComponentModel.DataAnnotations;

public class Person
{
    public int PersonID { get; set; }
    
    [MinLength(3), MaxLength(100)]
    public string PersonName { get; set; }    
}

La columna resultante con la longitud de columna especificada:

introduzca la descripción de la imagen aquí

El atributo [MinLength (int)] es un atributo de validación, no afecta la estructura de la base de datos. Si intentamos insertar / actualizar una Persona con Nombre de Persona con una longitud inferior a 3 caracteres, este compromiso fallará. DbUpdateConcurrencyException una DbUpdateConcurrencyException que necesitaremos manejar.

using (var db = new ApplicationDbContext())
{                    
     db.Staff.Add(new Person() { PersonName = "ng" });
     try
     {
          db.SaveChanges();
     }
     catch (DbEntityValidationException ex)
     {
          //ErrorMessage = "The field PersonName must be a string or array type with a minimum length of '3'."
     }
}

Los atributos [MaxLength] y [MinLength] también se pueden usar con asp.net-mvc como atributo de validación.

Atributo [Rango (min, max)]

Especifica un rango numérico mínimo y máximo para una propiedad.

using System.ComponentModel.DataAnnotations;   

public partial class Enrollment
{
    public int EnrollmentID { get; set; }
   
    [Range(0, 4)]
    public Nullable<decimal> Grade { get; set; }
}

Si intentamos insertar / actualizar un Grado con un valor fuera de rango, este compromiso fallará. DbUpdateConcurrencyException una DbUpdateConcurrencyException que necesitaremos manejar.

using (var db = new ApplicationDbContext())
{
    db.Enrollments.Add(new Enrollment() { Grade = 1000 });

    try
    {
        db.SaveChanges();
    }
    catch (DbEntityValidationException ex)
    {
        // Validation failed for one or more entities
    }
}

También se puede usar con asp.net-mvc como un atributo de validación.

Resultado:

introduzca la descripción de la imagen aquí

Atributo [DatabaseGenerated]

Especifica cómo la base de datos genera valores para la propiedad. Hay tres valores posibles:

  1. None especifica que los valores no son generados por la base de datos.
  2. Identity especifica que la columna es una columna de identidad , que normalmente se utiliza para las claves primarias de enteros.
  3. Computed especifica que la base de datos genera el valor para la columna.

Si el valor es distinto de None , Entity Framework no confirmará los cambios realizados en la propiedad en la base de datos.

De forma predeterminada (en función de StoreGeneratedIdentityKeyConvention ) una propiedad de clave entera se tratará como una columna de identidad. Para anular esta convención y obligarla a ser tratada como una columna sin identidad, puede utilizar el atributo DatabaseGenerated con un valor de None .

using System.ComponentModel.DataAnnotations.Schema;

public class Foo
{
    [Key]
    public int Id { get; set; } // identity (auto-increment) column
}

public class Bar
{
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.None)]
    public int Id { get; set; } // non-identity column
}

El siguiente SQL crea una tabla con una columna calculada:

CREATE TABLE [Person] (
    Name varchar(100) PRIMARY KEY,
    DateOfBirth Date NOT NULL,
    Age AS DATEDIFF(year, DateOfBirth, GETDATE())
)
GO

Para crear una entidad que represente los registros en la tabla anterior, necesitaría usar el atributo DatabaseGenerated con un valor de Computed .

[Table("Person")]
public class Person
{
    [Key, StringLength(100)]
    public string Name { get; set; }
    public DateTime DateOfBirth { get; set; }
    [DatabaseGenerated(DatabaseGeneratedOption.Computed)]
    public int Age { get; set; }
}

Atributo [NotMapped]

Por la convención de Code-First, Entity Framework crea una columna para cada propiedad pública que es de un tipo de datos compatible y tiene tanto un getter como un setter. La anotación [NotMapped] debe aplicarse a cualquier propiedad para la cual NO deseamos una columna en una tabla de base de datos.

Un ejemplo de una propiedad que podríamos no querer almacenar en la base de datos es el nombre completo de un estudiante basado en su nombre y apellido. Esto se puede calcular sobre la marcha y no es necesario almacenarlo en la base de datos.

public string FullName => string.Format("{0} {1}", FirstName, LastName);

La propiedad "FullName" tiene solo un getter y ningún setter, por lo que Entity Framework NO creará una columna para él.

Otro ejemplo de una propiedad que tal vez no queramos almacenar en la base de datos es el "AverageGrade" de un estudiante. No queremos obtener el AverageGrade a pedido; en cambio, podríamos tener una rutina en otro lugar que la calcule.

[NotMapped]
public float AverageGrade { set; get; }

El "AverageGrade" debe estar marcado como anotación [NotMapped] , de lo contrario, Entity Framework creará una columna para él.

using System.ComponentModel.DataAnnotations.Schema;

public class Student
{
    public int Id { set; get; }

    public string FirstName { set; get; }

    public string LastName { set; get; }

    public string FullName => string.Format("{0} {1}", FirstName, LastName);

    [NotMapped]
    public float AverageGrade { set; get; }
}

Para la Entidad anterior veremos dentro de DbMigration.cs

CreateTable(
    "dbo.Students",
     c => new
         {
             Id = c.Int(nullable: false, identity: true),
             FirstName = c.String(),
             LastName = c.String(),
         })
     .PrimaryKey(t => t.Id);

y en SQL Server Management Studio

introduzca la descripción de la imagen aquí

Atributo [tabla]

[Table("People")]
public class Person
{
    public int PersonID { get; set; }
    public string PersonName { get; set; }    
}

Le dice a Entity Framework que use un nombre de tabla específico en lugar de generar uno (es decir, Person o Persons )

También podemos especificar un esquema para la tabla usando el atributo [Tabla]

[Table("People", Schema = "domain")]

Atributo [columna]

public class Person
{
    public int PersonID { get; set; }
    
    [Column("NameOfPerson")]
    public string PersonName { get; set; }    
}

Le dice a Entity Framework que use un nombre de columna específico en lugar de usar el nombre de la propiedad. También puede especificar el tipo de datos de la base de datos y el orden de la columna en la tabla:

[Column("NameOfPerson", TypeName = "varchar", Order = 1)]
public string PersonName { get; set; }    

Atributo [índice]

public class Person
{
    public int PersonID { get; set; }
    public string PersonName { get; set; }

    [Index]
    public int Age { get; set; }
}

Crea un índice de base de datos para una columna o conjunto de columnas.

[Index("IX_Person_Age")]
public int Age { get; set; }

Esto crea un índice con un nombre específico.

[Index(IsUnique = true)]
public int Age { get; set; }

Esto crea un índice único.

[Index("IX_Person_NameAndAge", 1)]
public int Age { get; set; }

[Index("IX_Person_NameAndAge", 2)]
public string PersonName { get; set; }

Esto crea un índice compuesto utilizando 2 columnas. Para hacer esto, debe especificar el mismo nombre de índice y proporcionar un orden de columna.

Nota : el atributo Índice se introdujo en Entity Framework 6.1. Si está utilizando una versión anterior, la información en esta sección no se aplica.

Atributo [ForeignKey (cadena)]

Especifica el nombre de la clave externa personalizada si se desea una clave externa que no siga la convención de EF.

public class Person 
{
    public int IdAddress { get; set; }

    [ForeignKey(nameof(IdAddress))]
    public virtual Address HomeAddress { get; set; }
}

Esto también se puede usar cuando tienes varias relaciones con el mismo tipo de entidad.

using System.ComponentModel.DataAnnotations.Schema;

public class Customer
{
    ...

    public int MailingAddressID { get; set; }
    public int BillingAddressID { get; set; }

    [ForeignKey("MailingAddressID")]
    public virtual Address MailingAddress { get; set; }
    [ForeignKey("BillingAddressID")]
    public virtual Address BillingAddress { get; set; }
}

Sin los atributos de ForeignKey , EF podría mezclarlos y usar el valor de BillingAddressID al obtener la MailingAddress , o simplemente podría tener un nombre diferente para la columna en función de sus propias convenciones de nombres (como Address_MailingAddress_Id ) y tratar de usar eso en su lugar (lo que resultaría en un error si está usando esto con una base de datos existente).

Atributo [StringLength (int)]

using System.ComponentModel.DataAnnotations;

public class Post
{
    public int Id { get; set; }
    
    [StringLength(100)]
    public string Title { get; set;}

    [StringLength(300)]
    public string Abstract { get; set; }
    
    public string Description { get; set; }
}

Define una longitud máxima para un campo de cadena.

introduzca la descripción de la imagen aquí

Nota : También se puede usar con asp.net-mvc como un atributo de validación.

Atributo [marca de tiempo]

El atributo [TimeStamp] se puede aplicar a solo una propiedad de matriz de bytes en una clase de entidad dada. Entity Framework creará una columna de marca de tiempo no anulable en la tabla de la base de datos para esa propiedad. Entity Framework utilizará automáticamente esta columna de TimeStamp en la verificación de concurrencia.

using System.ComponentModel.DataAnnotations.Schema;

public class Student
{
    public int Id { set; get; }

    public string FirstName { set; get; }

    public string LastName { set; get; }    

    [Timestamp]
    public byte[] RowVersion { get; set; }
}

introduzca la descripción de la imagen aquí

Atributo [ConcurrencyCheck]

Este atributo se aplica a la propiedad de clase. Puede usar el atributo ConcurrencyCheck cuando desee usar columnas existentes para la comprobación de concurrencia y no una columna de marca de tiempo separada para la concurrencia.

using System.ComponentModel.DataAnnotations;

public class Author
{
    public int AuthorId { get; set; }
     
    [ConcurrencyCheck]
    public string AuthorName { get; set; }
}

Del ejemplo anterior, el atributo ConcurrencyCheck se aplica a la propiedad AuthorName de la clase Author. Por lo tanto, Code-First incluirá la columna AuthorName en el comando de actualización (donde cláusula) para verificar la concurrencia optimista.

Atributo [InverseProperty (cadena)]

using System.ComponentModel.DataAnnotations.Schema;

public class Department  
{  
    ...

    public virtual ICollection<Employee> PrimaryEmployees { get; set; }  
    public virtual ICollection<Employee> SecondaryEmployees { get; set; }  
}  
  
public class Employee  
{  
    ...

    [InverseProperty("PrimaryEmployees")]  
    public virtual Department PrimaryDepartment { get; set; }  
  
    [InverseProperty("SecondaryEmployees")]  
    public virtual Department SecondaryDepartment { get; set; }  
}  

InverseProperty se puede usar para identificar relaciones de dos vías cuando existen varias relaciones de dos vías entre dos entidades.

Le dice a Entity Framework qué propiedades de navegación deben coincidir con las propiedades en el otro lado.

Entity Framework no sabe qué mapa de propiedades de navegación con qué propiedades en el otro lado cuando existen varias relaciones bidireccionales entre dos entidades.

Necesita el nombre de la propiedad de navegación correspondiente en la clase relacionada como parámetro.

Esto también puede usarse para entidades que tienen una relación con otras entidades del mismo tipo, formando una relación recursiva.

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

public class TreeNode
{
    [Key]
    public int ID { get; set; }
    public int ParentID { get; set; }

    ...

    [ForeignKey("ParentID")]
    public TreeNode ParentNode { get; set; }
    [InverseProperty("ParentNode")]
    public virtual ICollection<TreeNode> ChildNodes { get; set; }
}

Tenga en cuenta también el uso del atributo ForeignKey para especificar la columna que se utiliza para la clave externa en la tabla. En el primer ejemplo, las dos propiedades en la clase Employee podrían haber tenido el atributo ForeignKey aplicado para definir los nombres de columna.

Atributo [ComplexType]

using System.ComponentModel.DataAnnotations.Schema;

[ComplexType] 
public class BlogDetails 
{ 
    public DateTime? DateCreated { get; set; } 
 
    [MaxLength(250)] 
    public string Description { get; set; } 
}

public class Blog
{
    ...

    public BlogDetails BlogDetail { get; set; }
}

Marque la clase como tipo complejo en Entity Framework.

Los tipos complejos (o los objetos de valor en diseño impulsado por dominio) no se pueden rastrear por sí solos, pero se rastrean como parte de una entidad. Esta es la razón por la que BlogDetails en el ejemplo no tiene una propiedad clave.

Tipo complejo siendo rastreado

Pueden ser útiles al describir entidades de dominio en varias clases y agrupar esas clases en una entidad completa.



Modified text is an extract of the original Stack Overflow Documentation
Licenciado bajo CC BY-SA 3.0
No afiliado a Stack Overflow