Общие сведения о связях
В этом документе представлено простое введение в представление связей в объектных моделях и реляционных базах данных, включая сопоставление 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.
Внимание
Одна связь обычно проходит в любом направлении. В этом примере это свойство осуществляется Post
Blog.Posts
через Blog
свойство и обратно 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
первичного Posts
ключа ссылается на BlogId
столбец Id
внешнего ключа таблицы. Этот столбец является "ограниченным", таким образом, что любое значение в BlogId
столбце Posts
должно соответствовать значению в столбце Id
Blogs
. Это совпадение определяет, с каким блогом связана каждая запись. Например, если 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 построения модели для некоторых аспектов конфигурации отношений.
Внимание
API построения модели является окончательным источником истины для модели EF. Она всегда имеет приоритет над конфигурацией, обнаруженной по соглашению или заданным атрибутами сопоставления. Это также единственный механизм с полной точностью для настройки каждого аспекта модели EF.
К другим темам, связанным с отношениями, относятся следующие:
- Каскадные удаления, описывающие автоматическое удаление связанных сущностей при
SaveChanges
вызове илиSaveChangesAsync
вызове. - Типы принадлежащих сущностей используют особый тип связи "владение", которая подразумевает более сильное соединение между двумя типами, чем "обычные" связи, рассмотренные здесь. Многие понятия, описанные здесь для обычных отношений, переносятся в собственные отношения. Однако собственные отношения также имеют собственное специальное поведение.
Совет
Ознакомьтесь с глоссарием терминов отношений при необходимости при чтении документации, чтобы понять используемую терминологию.
Использование связей
Связи, определенные в модели, можно использовать различными способами. Например:
- Связи можно использовать для запроса связанных данных любым из трех способов:
- С нетерпением в составе запроса LINQ, используя
Include
. - Ленивое использование отложенных прокси-серверов или отложенной загрузки без прокси-серверов.
- Явное использование
Load
методов илиLoadAsync
методов.
- С нетерпением в составе запроса LINQ, используя
- Связи можно использовать в заполнения данных путем сопоставления значений PK со значениями FK.
- Связи можно использовать для отслеживания графов сущностей. Затем связи используются средство отслеживания изменений:
- Обнаружение изменений в отношениях и выполнение исправления
- Отправка обновлений внешнего ключа в базу данных или
SaveChanges
SaveChangesAsync