Общие сведения о связях

В этом документе представлено простое введение в представление связей в объектных моделях и реляционных базах данных, включая то, как EF Core осуществляет сопоставление между ними.

Связи в объектных моделях

Связь определяет, как две сущности связаны друг с другом. Например, при моделировании записей в блоге каждая запись связана с блогом, на котором она опубликована, и блог связан со всеми записями, опубликованными в этом блоге.

В объектно-ориентированном языке, например C#, блог и запись обычно представлены двумя классами: Blog и Post. Например:

public class Blog
{
    public string Name { get; set; }
    public virtual Uri SiteUri { get; set; }
}
public class Post
{
    public string Title { get; set; }
    public string Content { get; set; }
    public DateTime PublishedOn { get; set; }
    public bool Archived { get; set; }
}

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

public class Post
{
    public string Title { get; set; }
    public string Content { get; set; }
    public DateOnly PublishedOn { get; set; }
    public bool Archived { get; set; }

    public Blog Blog { get; set; }
}

Аналогичным образом, противоположное направление того же отношения может быть представлено как коллекция Post объектов на каждом Blog:

public class Blog
{
    public string Name { get; set; }
    public virtual Uri SiteUri { get; set; }

    public ICollection<Post> Posts { get; }
}

Это подключение от Blog к Post, и, наоборот, от Post обратно к Blog называется "связью" в EF Core.

Внимание

Связь с одним обычно можно пройти в любом направлении. В этом примере, это от Blog до Post через свойство Blog.Posts, и обратно от Post до Blog через свойство Post.Blog. Это одна связь, а не две.

Совет

В EF Core свойства Blog.Posts и Post.Blog называются 'навигациями'.

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

Реляционные базы данных представляют отношения с помощью внешних ключей. Например, с помощью SQL Server или SQL Azure можно использовать следующие таблицы для представления наших Post и Blog классов:

CREATE TABLE [Posts] (
    [Id] int NOT NULL IDENTITY,
    [Title] nvarchar(max) NULL,
    [Content] nvarchar(max) NULL,
    [PublishedOn] datetime2 NOT NULL,
    [Archived] bit NOT NULL,
    [BlogId] int NOT NULL,
    CONSTRAINT [PK_Posts] PRIMARY KEY ([Id]),
    CONSTRAINT [FK_Posts_Blogs_BlogId] FOREIGN KEY ([BlogId]) REFERENCES [Blogs] ([Id]) ON DELETE CASCADE);

CREATE TABLE [Blogs] (
    [Id] int NOT NULL IDENTITY,
    [Name] nvarchar(max) NULL,
    [SiteUri] nvarchar(max) NULL,
    CONSTRAINT [PK_Blogs] PRIMARY KEY ([Id]));

В этой реляционной модели таблицы Posts и Blogs каждая получают столбец "первичный ключ". Значение первичного ключа однозначно идентифицирует каждую запись или блог. Кроме того, в таблицу Posts добавлен столбец "внешний ключ". Столбец Blogs первичного ключа Id является ссылочным для столбца BlogId внешнего ключа таблицы Posts. Этот столбец является "ограниченным", таким образом, что любое значение в BlogId столбце Posts должно соответствовать значению в столбце IdBlogs. Это совпадение определяет, с каким блогом связана каждая запись. Например, если BlogId значение в одной строке таблицы равно 7, то запись, представленная этой строкой Posts , публикуется в блоге с первичным ключом 7.

Сопоставление связей в EF Core

Сопоставление связей EF Core — это сопоставление первичного ключа или внешнего ключа, используемого в реляционной базе данных с ссылками между объектами, используемыми в объектной модели.

В самом базовом смысле это включает в себя:

  • Добавление свойства первичного ключа к каждому типу сущности.
  • Добавление свойства внешнего ключа одному типу сущности.
  • Связывание ссылок между типами сущностей с основными и внешними ключами для формирования единой конфигурации связи.

После внесения этого сопоставления EF изменяет значения внешнего ключа при необходимости при изменении ссылок между объектами и изменяет ссылки между объектами при необходимости при изменении значений внешнего ключа.

Примечание.

Первичные ключи используются не только для сопоставления отношений. Дополнительные сведения см. в разделе "Ключи ".

Например, указанные выше типы сущностей можно обновить с помощью свойств первичного и внешнего ключа:

public class Blog
{
    public int Id { get; set; }
    public string Name { get; set; }
    public virtual Uri SiteUri { get; set; }

    public ICollection<Post> Posts { get; }
}
public class Post
{
    public int Id { get; set; }
    public string Title { get; set; }
    public string Content { get; set; }
    public DateTime PublishedOn { get; set; }
    public bool Archived { get; set; }

    public int BlogId { get; set; }
    public Blog Blog { get; set; }
}

Совет

Свойства первичного и внешнего ключа не должны быть общедоступными видимыми свойствами типа сущности. Однако даже если свойства скрыты, важно признать, что они по-прежнему существуют в модели EF.

Свойство первичного Blogключа , Blog.Idа также свойство внешнего ключа Post, Post.BlogIdзатем может быть связано со ссылками ("навигации") между типами сущностей (Blog.Posts и Post.Blog). EF выполняет это автоматически при создании подобной простой связи, но можно также задать явно, когда вы переопределяете метод OnModelCreating вашего DbContext. Например:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Blog>()
        .HasMany(e => e.Posts)
        .WithOne(e => e.Blog)
        .HasForeignKey(e => e.BlogId)
        .HasPrincipalKey(e => e.Id);
}

Теперь все эти свойства будут вести себя последовательно как представление одной связи между Blog и Post.

Подробнее

EF поддерживает множество различных типов связей с различными способами представления и настройки этих связей. Чтобы перейти к примерам различных типов связей, см. следующие сведения:

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

Если вы не знакомы с EF, то попробовать примеры, перечисленные в указанных выше маркированных списках, — это хороший способ понять, как работают взаимоотношения.

Дополнительные сведения о свойствах типов сущностей, участвующих в сопоставлении связей, см. в следующих статье:

Модели EF создаются с помощью трех механизмов: соглашений, атрибутов сопоставления и API построителя моделей. В большинстве примеров показан API построения модели. Дополнительные сведения о других вариантах см. в следующем разделе:

Внимание

API построения модели является окончательным источником истины для модели EF. Она всегда имеет приоритет над конфигурацией, обнаруженной по соглашению или заданным атрибутами сопоставления. Это также единственный механизм с полной точностью для настройки каждого аспекта модели EF.

К другим темам, связанным с отношениями, относятся следующие:

  • Каскадные удаления, описывающие автоматическое удаление связанных сущностей при вызове SaveChanges или SaveChangesAsync.
  • Типы принадлежащих сущностей используют особый тип связи "владение", которая подразумевает более сильное соединение между двумя типами, чем "обычные" связи, рассмотренные здесь. Многие понятия, описанные здесь для нормальных отношений, переносятся на отношения владения. Однако владельческие отношения также имеют своё особое поведение.

Совет

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

Использование связей

Связи, определенные в модели, можно использовать различными способами. Например: