Соглашения о коде

Code First позволяет описать модель с помощью классов C# или Visual Basic .NET. Базовая форма модели обнаруживается с помощью соглашений. Соглашения — это наборы правил, которые используются для автоматической настройки концептуальной модели на основе определений классов при работе с кодом First. Соглашения определяются в пространстве имен System.Data.Entity.ModelConfiguration.Conventions.

Вы можете дополнительно настроить модель с помощью заметок данных или api fluent. Приоритет присваивается конфигурации через простой API, за которым следует заметки данных, а затем соглашения. Дополнительные сведения см. в заметках к данным, API Fluent — связи, API Fluent — Типы и свойства и API Fluent с VB.NET.

Подробный список соглашений Code First доступен в документации по API. В этом разделе представлен обзор соглашений, используемых code First.

Обнаружение типов

При использовании разработки Code First вы обычно начинаете с написания платформа .NET Framework классов, определяющих концептуальную модель (домен). Помимо определения классов, необходимо также сообщить DbContext о типах, которые необходимо включить в модель. Для этого необходимо определить класс контекста, производный от DbContext и предоставляющий свойства DbSet для типов, которые вы хотите быть частью модели. Code First будет включать эти типы, а также будет извлекать любые ссылочные типы, даже если указанные типы определены в другой сборке.

Если типы участвуют в иерархии наследования, достаточно определить свойство DbSet для базового класса, а производные типы будут автоматически включены, если они находятся в той же сборке, что и базовый класс.

В следующем примере существует только одно свойство DbSet , определенное в классе SchoolEntities (Departments). Код сначала использует это свойство для обнаружения и извлечения всех ссылочных типов.

public class SchoolEntities : DbContext
{
    public DbSet<Department> Departments { get; set; }
}

public class Department
{
    // Primary key
    public int DepartmentID { get; set; }
    public string Name { get; set; }

    // Navigation property
    public virtual ICollection<Course> Courses { get; set; }
}

public class Course
{
    // Primary key
    public int CourseID { get; set; }

    public string Title { get; set; }
    public int Credits { get; set; }

    // Foreign key
    public int DepartmentID { get; set; }

    // Navigation properties
    public virtual Department Department { get; set; }
}

public partial class OnlineCourse : Course
{
    public string URL { get; set; }
}

public partial class OnsiteCourse : Course
{
    public string Location { get; set; }
    public string Days { get; set; }
    public System.DateTime Time { get; set; }
}

Если вы хотите исключить тип из модели, используйте атрибут NotMapped или API DbModelBuilder.Ignore fluent.

modelBuilder.Ignore<Department>();

Соглашение о первичном ключе

Сначала код определяет, что свойство является первичным ключом, если свойство класса называется "ID" (не учитывает регистр), или имя класса, за которым следует идентификатор. Если тип свойства первичного ключа является числовым или GUID, он будет настроен в качестве столбца удостоверения.

public class Department
{
    // Primary key
    public int DepartmentID { get; set; }

    . . .  

}

Соглашение о связи

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

Помимо свойств навигации рекомендуется включить свойства внешнего ключа в типы, представляющие зависимые объекты. Любое свойство с тем же типом данных, что и свойство основного первичного ключа и имя, которое следует одному из следующих форматов, представляет внешний ключ для связи: "<имя свойства навигации><имя основного ключа первичного> ключа", "<имя><основного класса имени первичного ключа" или "<имя>> основного свойства первичного ключа". Если найдено несколько совпадений, приоритет присваивается в указанном выше порядке. Обнаружение внешнего ключа не учитывает регистр. При обнаружении свойства внешнего ключа код сначала определяет кратность связи на основе допустимости null внешнего ключа. Если свойство равно null, то связь регистрируется как необязательное; в противном случае связь регистрируется по мере необходимости.

Если внешний ключ для зависимой сущности не имеет значения NULL, код сначала задает каскадное удаление связи. Если внешний ключ зависимой сущности имеет значение NULL, code First не устанавливает каскадное удаление связи, а при удалении внешнего ключа субъект будет иметь значение NULL. Кратность и каскадное удаление, обнаруженные соглашением, можно переопределить с помощью API fluent.

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

public class Department
{
    // Primary key
    public int DepartmentID { get; set; }
    public string Name { get; set; }

    // Navigation property
    public virtual ICollection<Course> Courses { get; set; }
}

public class Course
{
    // Primary key
    public int CourseID { get; set; }

    public string Title { get; set; }
    public int Credits { get; set; }

    // Foreign key
    public int DepartmentID { get; set; }

    // Navigation properties
    public virtual Department Department { get; set; }
}

Примечание.

Если у вас есть несколько связей между одинаковыми типами (например, предположим, что вы определяете класс Person и Book, где класс Person содержит свойства навигации ReviewedBooks и AuthoredBooks, а класс Book содержит свойства навигации "Автор и рецензент") необходимо вручную настроить отношения с помощью заметок данных или свободного API. Дополнительные сведения см. в разделе "Заметки данных" — связи и API Fluent — связи.

Соглашение о сложных типах

Когда Code First обнаруживает определение класса, в котором первичный ключ не может быть выведен, и первичный ключ не регистрируется с помощью заметок данных или api fluent, то тип автоматически регистрируется в качестве сложного типа. Для обнаружения сложных типов также требуется, чтобы тип не имеет свойств, которые ссылаются на типы сущностей и не ссылаются из свойства коллекции другого типа. Учитывая следующие определения классов Code First, будут выводить, что Details является сложным типом, так как он не имеет первичного ключа.

public partial class OnsiteCourse : Course
{
    public OnsiteCourse()
    {
        Details = new Details();
    }

    public Details Details { get; set; }
}

public class Details
{
    public System.DateTime Time { get; set; }
    public string Location { get; set; }
    public string Days { get; set; }
}

Соглашение о строке Подключение ion

Сведения о соглашениях, используемых DbContext для обнаружения подключения для использования Подключение и моделей.

Удаление соглашений

Вы можете удалить любое из соглашений, определенных в пространстве имен System.Data.Entity.ModelConfiguration.Conventions. В следующем примере удаляется PluralizingTableNameConvention.

public class SchoolEntities : DbContext
{
     . . .

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        // Configure Code First to ignore PluralizingTableName convention
        // If you keep this convention, the generated tables  
        // will have pluralized names.
        modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
    }
}

Настраиваемые соглашения

Пользовательские соглашения поддерживаются в EF6. Дополнительные сведения см . в соглашениях о первом коде.