Поиск…


замечания

Entity Framework Code-First предоставляет набор атрибутов DataAnnotation, которые вы можете применить к своим классам и свойствам домена. Атрибуты DataAnnotation переопределяют стандартные соглашения Code-First.

  1. System.ComponentModel.DataAnnotations включает атрибуты, которые влияют на нулеустойчивость или размер столбца.
  2. System.ComponentModel.DataAnnotations.Schema namespace включает атрибуты, которые влияют на схему базы данных.

Примечание. DataAnnotations предоставляет только набор параметров конфигурации. Fluent API предоставляет полный набор параметров конфигурации, доступных в Code-First.

Атрибут [Key]

Ключ - это поле в таблице, которое однозначно идентифицирует каждую строку / запись в таблице базы данных.

Используйте этот атрибут, чтобы переопределить стандартное соглашение Code-First . Если применяется к свойству, он будет использоваться в качестве столбца первичного ключа для этого класса.

using System.ComponentModel.DataAnnotations;

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

Если требуется составной первичный ключ, атрибут [Key] можно также добавить к нескольким свойствам. Порядок столбцов в составном ключе должен быть указан в форме [ Ключ, Столбец (Заказ = 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; }    
}

Без атрибута [Key] EntityFramework вернется к соглашению по умолчанию, которое должно использовать свойство класса в качестве первичного ключа с именем «Id» или «{ClassName} Id».

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

[Обязательный] атрибут

При применении к свойству класса домена база данных создаст столбец NOT NULL.

using System.ComponentModel.DataAnnotations;

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

Полученный столбец с ограничением NOT NULL:

Полученный столбец в SQL Server

Примечание. Его также можно использовать с asp.net-mvc в качестве атрибута проверки.

[MaxLength] и [MinLength]

Атрибут [MaxLength (int)] может применяться к свойству типа строки или массива класса домена. Entity Framework установит размер столбца на указанное значение.

using System.ComponentModel.DataAnnotations;

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

Полученный столбец с указанной длиной столбца:

введите описание изображения здесь

[MinLength (int)] - атрибут проверки, он не влияет на структуру базы данных. Если мы попытаемся вставить / обновить Person с PersonName длиной менее 3 символов, это сообщение не будет выполнено. Мы получим DbUpdateConcurrencyException которое нам нужно будет обработать.

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

Оба атрибута [MaxLength] и [MinLength] также могут использоваться с asp.net-mvc в качестве атрибута проверки.

[Range (min, max)] атрибут

Указывает числовой минимальный и максимальный диапазон для свойства

using System.ComponentModel.DataAnnotations;   

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

Если мы попытаемся вставить / обновить класс со значением вне диапазона, это сообщение не будет выполнено. Мы получим DbUpdateConcurrencyException которое нам нужно будет обработать.

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

Он также может использоваться с asp.net-mvc в качестве атрибута проверки.

Результат:

введите описание изображения здесь

Атрибут [DatabaseGenerated]

Указывает, как база данных генерирует значения для свойства. Существует три возможных значения:

  1. None указывает, что значения не генерируются базой данных.
  2. Identity указывает, что столбец является столбцом идентификации , который обычно используется для целых первичных ключей.
  3. Computed указывает, что база данных генерирует значение для столбца.

Если значение имеет значение, отличное от None , Entity Framework не будет вносить изменения, внесенные в свойство обратно в базу данных.

По умолчанию (на основе StoreGeneratedIdentityKeyConvention ) свойство целочисленного ключа будет рассматриваться как столбец идентификатора. Чтобы переопределить это соглашение и заставить его обрабатывать как столбец не идентичности, вы можете использовать атрибут DatabaseGenerated со значением 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
}

Следующий SQL создает таблицу с вычисленным столбцом:

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

Чтобы создать объект для представления записей в приведенной выше таблице, вам нужно будет использовать атрибут DatabaseGenerated со значением 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; }
}

Атрибут [NotMapped]

По соглашению Code-First Entity Framework создает столбец для каждого общедоступного свойства поддерживаемого типа данных и имеет как getter, так и setter. Аннотации [NotMapped] должны применяться к любым свойствам, для которых нам НЕ нужен столбец в таблице базы данных.

Примером свойства, которое мы не хотим хранить в базе данных, является полное имя студента, основанное на их имени и фамилии. Это можно вычислить «на лету», и нет необходимости хранить его в базе данных.

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

Свойство «FullName» имеет только getter и setter, поэтому по умолчанию Entity Framework НЕ создаст для него столбец.

Другим примером свойства, которое мы, возможно, не хотим хранить в базе данных, является «Средняя оценка» учащегося. Мы не хотим получать AverageGrade по запросу; вместо этого у нас может быть рутина в другом месте, которая ее вычисляет.

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

«AverageGrade» должен быть помечен аннотацией [NotMapped] , иначе Entity Framework создаст для него столбец.

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

Для вышеупомянутого DbMigration.cs мы увидим внутри DbMigration.cs

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

и в SQL Server Management Studio

введите описание изображения здесь

Атрибут [Таблица]

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

Сообщает Entity Framework использовать конкретное имя таблицы вместо создания одного (то есть Person или Persons )

Мы также можем указать схему для таблицы, используя атрибут [Таблица]

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

Атрибут [Столбец]

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

Сообщает Entity Framework вместо использования имени столбца вместо имени свойства. Вы также можете указать тип данных базы данных и порядок столбца в таблице:

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

Атрибут [Index]

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

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

Создает индекс базы данных для столбца или набора столбцов.

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

Это создает индекс с определенным именем.

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

Это создает уникальный индекс.

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

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

Это создает составной индекс, используя 2 столбца. Для этого вы должны указать одно и то же имя индекса и указать порядок столбцов.

Примечание . Атрибут Index был введен в Entity Framework 6.1. Если вы используете более раннюю версию, информация в этом разделе не применяется.

Атрибут [ForeignKey (string)]

Указывает имя пользовательского внешнего ключа, если требуется внешний ключ, не соответствующий соглашению EF.

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

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

Это также можно использовать, если у вас несколько отношений с одним типом объекта.

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

Без атрибутов ForeignKey EF может их перепутать и использовать значение BillingAddressID при извлечении MailingAddress , или просто может возникнуть другое имя для столбца на основе его собственных соглашений об именах (например, Address_MailingAddress_Id ) и попытаться использовать это вместо этого (что приведет к ошибке, если вы используете это с существующей базой данных).

Атрибут [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; }
}

Определяет максимальную длину для строкового поля.

введите описание изображения здесь

Примечание . Его также можно использовать с asp.net-mvc в качестве атрибута проверки.

Атрибут [Timestamp]

Атрибут [TimeStamp] может применяться только к одному свойству байтового массива в данном классе Entity. Entity Framework создаст в таблице базы данных столбец с нулевым значением в таблице базы данных для этого свойства. Entity Framework автоматически использует этот столбец TimeStamp при проверке параллелизма.

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

введите описание изображения здесь

Атрибут [ConcurrencyCheck]

Этот атрибут применяется к свойству класса. Вы можете использовать атрибут ConcurrencyCheck, если хотите использовать существующие столбцы для проверки параллелизма, а не отдельный столбец временной отметки для параллелизма.

using System.ComponentModel.DataAnnotations;

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

В приведенном выше примере атрибут ConcurrencyCheck применяется к свойству AuthorName класса Author. Итак, Code-First будет включать столбец AuthorName в команде update (where clause), чтобы проверить оптимистичный параллелизм.

Атрибут [InverseProperty (string)]

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 может использоваться для идентификации двухсторонних отношений, когда между двумя сущностями существуют несколько двухсторонних отношений.

Он сообщает Entity Framework, какие свойства навигации должны соответствовать свойствам с другой стороны.

Entity Framework не знает, какая карта навигации имеет свойства с другой стороны, когда существуют несколько двунаправленных отношений между двумя объектами.

В качестве своего параметра ему нужно имя соответствующего свойства навигации в соответствующем классе.

Это также можно использовать для объектов, которые имеют отношение к другим объектам того же типа, образуя рекурсивное отношение.

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

Обратите также внимание на использование атрибута ForeignKey для указания столбца, который используется для внешнего ключа в таблице. В первом примере два свойства класса Employee могли иметь атрибут ForeignKey для определения имен столбцов.

Атрибут [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; }
}

Пометьте класс как сложный тип в Entity Framework.

Сложные типы (или объекты ценности в проекте, управляемом доменом) не могут отслеживаться самостоятельно, но отслеживаются как часть объекта. Вот почему BlogDetails в этом примере не имеет свойства ключа.

Отслеживается сложный тип

Они могут быть полезны при описании сущностей домена на нескольких классах и разбиении этих классов на полный объект.



Modified text is an extract of the original Stack Overflow Documentation
Лицензировано согласно CC BY-SA 3.0
Не связан с Stack Overflow