Recherche…


Remarques

Entity Framework Code-First fournit un ensemble d'attributs DataAnnotation, que vous pouvez appliquer à vos classes et propriétés de domaine. Les attributs DataAnnotation remplacent les conventions Code-First par défaut.

  1. System.ComponentModel.DataAnnotations inclut des attributs qui ont un impact sur la nullité ou la taille de la colonne.
  2. L' espace de noms System.ComponentModel.DataAnnotations.Schema inclut des attributs qui ont un impact sur le schéma de la base de données.

Remarque: DataAnnotations ne vous donne qu'un sous-ensemble d'options de configuration. Fluent API fournit un ensemble complet d'options de configuration disponibles dans Code-First.

Attribut [Key]

Key est un champ dans une table qui identifie de manière unique chaque ligne / enregistrement dans une table de base de données.

Utilisez cet attribut pour remplacer la convention Code-First par défaut . Si elle est appliquée à une propriété, elle sera utilisée comme colonne de clé primaire pour cette classe.

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 une clé primaire composite est requise, l'attribut [Key] peut également être ajouté à plusieurs propriétés. L'ordre des colonnes dans la clé composite doit être fourni sous la forme [ Key, Column (Order = 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; }    
}

Sans l'attribut [Key] , EntityFramework utilisera la convention par défaut qui consiste à utiliser la propriété de la classe en tant que clé primaire nommée "Id" ou "{ClassName} Id".

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

Attribut [obligatoire]

Appliquée à une propriété d'une classe de domaine, la base de données créera une colonne NOT NULL.

using System.ComponentModel.DataAnnotations;

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

La colonne résultante avec la contrainte NOT NULL:

La colonne résultante dans un serveur SQL

Remarque: il peut également être utilisé avec asp.net-mvc comme attribut de validation.

Attributs [MaxLength] et [MinLength]

L' attribut [MaxLength (int)] peut être appliqué à une propriété de type chaîne ou tableau d'une classe de domaine. Entity Framework définira la taille d'une colonne sur la valeur spécifiée.

using System.ComponentModel.DataAnnotations;

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

La colonne résultante avec la longueur de colonne spécifiée:

entrer la description de l'image ici

L'attribut [MinLength (int)] est un attribut de validation, il n'affecte pas la structure de la base de données. Si nous essayons d'insérer / mettre à jour une personne avec PersonName avec une longueur inférieure à 3 caractères, cette validation échouera. Nous allons obtenir une DbUpdateConcurrencyException que nous devrons gérer.

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'."
     }
}

Les attributs [MaxLength] et [MinLength] peuvent également être utilisés avec asp.net-mvc comme attribut de validation.

[Range (min, max)] attribut

Spécifie une plage numérique minimale et maximale pour une propriété

using System.ComponentModel.DataAnnotations;   

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

Si nous essayons d'insérer / mettre à jour une note avec une valeur hors limites, cette validation échouera. Nous allons obtenir une DbUpdateConcurrencyException que nous devrons gérer.

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
    }
}

Il peut également être utilisé avec asp.net-mvc comme attribut de validation.

Résultat:

entrer la description de l'image ici

Attribut [DatabaseGenerated]

Spécifie comment la base de données génère des valeurs pour la propriété. Il y a trois valeurs possibles:

  1. None spécifie que les valeurs ne sont pas générées par la base de données.
  2. Identity spécifie que la colonne est une colonne d'identité , généralement utilisée pour les clés primaires entières.
  3. Computed spécifie que la base de données génère la valeur pour la colonne.

Si la valeur est différente de None , Entity Framework ne remet pas les modifications apportées à la propriété dans la base de données.

Par défaut (basé sur StoreGeneratedIdentityKeyConvention ), une propriété de clé entière sera traitée comme une colonne d'identité. Pour remplacer cette convention et la forcer à être traitée comme une colonne sans identité, vous pouvez utiliser l'attribut DatabaseGenerated avec la valeur 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
}

Le code SQL suivant crée une table avec une colonne calculée:

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

Pour créer une entité pour représenter les enregistrements du tableau ci-dessus, vous devez utiliser l'attribut DatabaseGenerated avec la valeur 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; }
}

Attribut [NotMapped]

Selon la convention Code-First, Entity Framework crée une colonne pour chaque propriété publique d'un type de données pris en charge et dispose à la fois d'un getter et d'un setter. L' annotation [NotMapped] doit être appliquée à toutes les propriétés pour lesquelles nous ne voulons PAS une colonne dans une table de base de données.

Un exemple de propriété que nous pourrions ne pas vouloir stocker dans la base de données est le nom complet de l'étudiant, basé sur son prénom et son nom. Cela peut être calculé à la volée et il n'est pas nécessaire de le stocker dans la base de données.

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

La propriété "FullName" n'a qu'un getter et aucun setter. Par défaut, Entity Framework ne créera PAS de colonne pour cela.

Un autre exemple de propriété que nous pourrions ne pas vouloir stocker dans la base de données est le "AverageGrade" d'un étudiant. Nous ne voulons pas obtenir le AverageGrade à la demande; au lieu de cela, nous pourrions avoir une routine ailleurs qui le calcule.

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

Le "AverageGrade" doit être marqué [NotMapped] , sinon Entity Framework créera une colonne pour cela.

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; }
}

Pour l'entité ci-dessus, nous verrons à l'intérieur 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);

et dans SQL Server Management Studio

entrer la description de l'image ici

Attribut [Table]

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

Indique à Entity Framework d'utiliser un nom de table spécifique au lieu d'en générer un (c.-à-d. Une Person ou des Persons )

Nous pouvons également spécifier un schéma pour la table en utilisant l'attribut [Table]

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

Attribut [Column]

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

Indique à Entity Framework d'utiliser un nom de colonne spécifique à la place en utilisant le nom de la propriété. Vous pouvez également spécifier le type de données de la base de données et l'ordre de la colonne dans la table:

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

Attribut [Index]

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

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

Crée un index de base de données pour une colonne ou un ensemble de colonnes.

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

Cela crée un index avec un nom spécifique.

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

Cela crée un index unique.

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

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

Cela crée un index composite utilisant 2 colonnes. Pour ce faire, vous devez spécifier le même nom d'index et fournir un ordre de colonne.

Remarque : L'attribut Index a été introduit dans Entity Framework 6.1. Si vous utilisez une version antérieure, les informations de cette section ne s’appliquent pas.

Attribut [ForeignKey (string)]

Spécifie le nom de la clé étrangère personnalisée si une clé étrangère ne respectant pas la convention EF est souhaitée.

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

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

Cela peut également être utilisé lorsque vous avez plusieurs relations avec le même type d'entité.

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; }
}

Sans les attributs ForeignKey , EF pourrait les mélanger et utiliser la valeur de BillingAddressID lors de l'extraction de MailingAddress , ou il pourrait simplement proposer un nom différent pour la colonne en fonction de ses propres conventions de nommage (comme Address_MailingAddress_Id ) et essayer de l'utiliser. au lieu de cela (ce qui entraînerait une erreur si vous l'utilisez avec une base de données existante).

[StringLength (int)] attribut

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; }
}

Définit une longueur maximale pour un champ de chaîne.

entrer la description de l'image ici

Remarque : il peut également être utilisé avec asp.net-mvc comme attribut de validation.

Attribut [Horodatage]

L' attribut [TimeStamp] ne peut être appliqué qu'à une propriété de tableau d'octets dans une classe d'entité donnée. Entity Framework créera une colonne d'horodatage non nullable dans la table de base de données pour cette propriété. Entity Framework utilisera automatiquement cette colonne TimeStamp dans la vérification de la concurrence.

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; }
}

entrer la description de l'image ici

[ConcurrencyCheck] Attribut

Cet attribut est appliqué à la propriété de classe. Vous pouvez utiliser l'attribut ConcurrencyCheck lorsque vous souhaitez utiliser des colonnes existantes pour la vérification de la concurrence et non une colonne d'horodatage distincte pour la concurrence.

using System.ComponentModel.DataAnnotations;

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

Par exemple, l'attribut ConcurrencyCheck est appliqué à la propriété AuthorName de la classe Author. Ainsi, Code-First inclura la colonne AuthorName dans la commande update (clause where) pour vérifier la concurrence optimiste.

[InverseProperty (string)] attribut

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 peut être utilisé pour identifier des relations bidirectionnelles lorsque plusieurs relations bidirectionnelles existent entre deux entités.

Il indique à Entity Framework les propriétés de navigation auxquelles il doit correspondre avec les propriétés de l'autre côté.

Entity Framework ne sait pas quelle carte de propriété de navigation avec quelles propriétés de l'autre côté lorsque plusieurs relations bidirectionnelles existent entre deux entités.

Il a besoin du nom de la propriété de navigation correspondante dans la classe associée en tant que paramètre.

Cela peut également être utilisé pour les entités qui ont une relation avec d'autres entités du même type, formant une relation récursive.

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; }
}

Notez également l'utilisation de l'attribut ForeignKey pour spécifier la colonne utilisée pour la clé étrangère sur la table. Dans le premier exemple, l'attribut ForeignKey la classe Employee pouvait être utilisé pour définir les noms de colonne.

Attribut [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; }
}

Marquez la classe en tant que type complexe dans Entity Framework.

Les types complexes (ou objets de valeur dans la conception pilotée par un domaine) ne peuvent pas être suivis par eux-mêmes, mais ils font l'objet d'un suivi dans le cadre d'une entité. C'est pourquoi BlogDetails dans l'exemple n'a pas de propriété clé.

Type complexe en cours de suivi

Ils peuvent être utiles pour décrire des entités de domaine dans plusieurs classes et superposer ces classes dans une entité complète.



Modified text is an extract of the original Stack Overflow Documentation
Sous licence CC BY-SA 3.0
Non affilié à Stack Overflow