Entity framework отношение не существует
В этой статье приводятся общие сведения о том, как Entity Framework управляет связями между сущностями. Кроме того, здесь приводятся некоторые рекомендации по сопоставлению и управлению связями.
Синхронизация изменений между внешними ключами и свойствами навигации
При изменении связи объектов, присоединенных к контексту с помощью одного из описанных выше методов, Entity Framework необходимо синхронизировать внешние ключи, ссылки и коллекции. Entity Framework автоматически управляет этой синхронизацией (также называется исправлением связи) для сущностей POCO с прокси-серверами. Дополнительные сведения см. в разделе Работа с учетными записями-посредниками.
При использовании сущностей POCO без прокси-серверов необходимо убедиться в том, что метод DetectChanges вызывается для синхронизации связанных объектов в контексте. Обратите внимание, что следующие интерфейсы API автоматически активируют вызов DetectChanges .
- DbSet.Add
- DbSet.AddRange
- DbSet.Remove
- DbSet.RemoveRange
- DbSet.Find
- DbSet.Local
- DbContext.SaveChanges
- DbSet.Attach
- DbContext.GetValidationErrors
- DbContext.Entry
- DbChangeTracker.Entries
- Выполнение запроса LINQ к элементу DbSet
Полностью определенные связи
Наиболее распространенным шаблоном связей является определение свойств навигации на обоих концах связи и свойство внешнего ключа, определенное в зависимом классе сущностей.
Если пара свойств навигации найдена между двумя типами, они будут настроены как обратные свойства навигации одного и того же отношения.
Если зависимая сущность содержит свойство с именем, соответствующим одному из этих шаблонов, он будет настроен как внешний ключ:
В этом примере выделенные свойства будут использоваться для настройки связи.
Если свойство является первичным ключом или имеет тип, несовместимый с основным ключом, он не будет настроен как внешний ключ.
Определение терминов
Существует ряд терминов, используемых для описания связей
Зависимый объект: Это сущность, содержащая свойства внешнего ключа. Иногда называют "дочерним" отношения.
Сущность субъекта: Это сущность, содержащая свойства первичного или альтернативного ключа. Иногда называют "родительским" отношением.
Ключ субъекта: Свойства, однозначно определяющие сущность субъекта. Это может быть первичный ключ или альтернативный ключ.
Внешний ключ: Свойства в зависимой сущности, которые используются для хранения значений основного ключа для связанной сущности.
Свойство навигации: Свойство, определенное для основной и (или) зависимой сущности, ссылающейся на связанную сущность.
Свойство навигации коллекции: Свойство навигации, содержащее ссылки на многие связанные сущности.
Эталонное свойство навигации: Свойство навигации, которое содержит ссылку на одну связанную сущность.
Свойство обратной навигации: При обсуждении определенного свойства навигации этот термин относится к свойству навигации в другом конце связи.
Связь с самонаправляющимися объектами: Связь, в которой зависимые и основные типы сущностей совпадают.
В следующем коде показана связь "один ко многим" между Blog и Post
Post является зависимой сущностью
Blog является основной сущностью
Blog.BlogId — это основной ключ (в данном случае это первичный ключ, а не альтернативный ключ).
Post.BlogId является внешним ключом
Post.Blog является ссылочным свойством навигации
Blog.Posts — это свойство навигации по коллекции
Post.Blog — это обратное свойство навигации Blog.Posts (и наоборот)
Ключ субъекта
Если внешний ключ будет ссылаться на свойство, отличное от первичного ключа, можно использовать API Fluent для настройки свойства ключа субъекта для связи. Свойство, которое вы настраиваете в качестве основного ключа, будет автоматически настроено в качестве альтернативного ключа.
Порядок, в котором указываются свойства ключа субъекта, должен соответствовать порядку, в котором они указаны для внешнего ключа.
Ограничения
При наличии нескольких свойств навигации, определенных между двумя типами (т. е. несколькими парами навигаций, которые указывают друг на друга), связи, представленные свойствами навигации, являются неоднозначными. Вам потребуется вручную настроить их для разрешения неоднозначности.
Другие шаблоны связей
2 ответа
Похоже, вы пытаетесь расширить EntityB с помощью необязательной ссылки 1: 1 на строку в новой таблице EntityA . Вы хотите, чтобы обе записи имели одинаковое значение Id.
Эта ссылка 1: 1 иногда называется Разделение таблицы .
Логически в вашем приложении записи из EntityB и EntityA представляют один и тот же объект бизнес-домена.
Если вы просто пытались создать обычную связь 1 : many , вам следует удалить HasOne (). WithOne () , поскольку это создает 1:1 , вы также не пытались бы чтобы вернуть FK к свойству Id.
Без свойства навигации
Необязательно указывать свойство навигации. Вы можете просто предоставить внешний ключ на одной стороне связи.
Один к одному
Один к одному отношениям имеет свойство навигации ссылок с обеих сторон. Они следуют тем же соглашениям, что и связи "один ко многим", но уникальный индекс вводится в свойстве внешнего ключа, чтобы гарантировать, что только один зависимый связан с каждым субъектом.
EF выберет одну из сущностей в зависимости от его способности обнаруживать свойство внешнего ключа. Если неправильная сущность выбрана в качестве зависимой, вы можете использовать API Fluent для исправления этой ошибки.
При настройке связи с API Fluent используются HasOne методы и WithOne методы.
При настройке внешнего ключа необходимо указать зависимый тип сущности. Обратите внимание на универсальный параметр, предоставленный HasForeignKey в приведенном ниже списке. В связи "один ко многим" ясно, что сущность со ссылкой является зависимой, а одна с коллекцией является основной. Но это не так в связи "один к одному" - следовательно, необходимость явно определить его.
Зависимые стороны считаются необязательными по умолчанию, но могут быть настроены по мере необходимости. Однако EF не будет проверять, была ли предоставлена зависимой сущностью, поэтому эта конфигурация будет иметь значение только при условии, что сопоставление базы данных позволяет применять ее. Типичным сценарием для этого являются ссылочные типы, использующие разделение таблиц по умолчанию.
При такой конфигурации столбцы, соответствующие этому параметру ShippingAddress , будут помечены как не допускающие значения NULL в базе данных.
Если вы используете вызов IsRequired ссылочных типов, не допускающих значения NULL, не требуется.
Возможность настройки необходимости зависимого в EF Core 5.0.
Соглашения
По умолчанию связь создается при обнаружении свойства навигации в типе. Свойство считается свойством навигации, если тип, на который он указывает, невозможно сопоставить как скалярный тип текущим поставщиком базы данных.
Связи, обнаруженные по соглашению, всегда будут нацелены на первичный ключ основной сущности. Чтобы выбрать альтернативный ключ, необходимо выполнить дополнительную настройку с помощью API Fluent.
Каскадное удаление
API Fluent можно использовать для явной настройки поведения каскадного удаления для данной связи.
Подробные сведения о каждом из вариантов см. в разделе "Каскадное удаление ".
Обязательные и необязательные связи
Api Fluent можно использовать для настройки того, является ли связь обязательной или необязательной. В конечном счете это определяет, является ли свойство внешнего ключа обязательным или необязательным. Это наиболее полезно при использовании внешнего ключа теневого состояния. Если в классе сущности есть свойство внешнего ключа, необходимое отношение определяется в зависимости от того, является ли свойство внешнего ключа обязательным или необязательным (дополнительные сведения см. в разделе "Обязательные и необязательные свойства ").
Свойства внешнего ключа находятся в зависимом типе сущности, поэтому если они настроены по мере необходимости, это означает, что для каждой зависимой сущности требуется соответствующая сущность субъекта.
Вызов IsRequired(false) также делает свойство внешнего ключа необязательным, если оно не настроено в противном случае.
Загрузка связанных объектов
В Entity Framework свойства навигации обычно используются для загрузки сущностей, связанных с возвращаемой сущностью, с помощью заданной ассоциации. Дополнительные сведения см. в разделе Загрузка связанных объектов.
В сопоставлении на основе внешнего ключа при загрузке связанного конечного элемента зависимого объекта связанный объект загружается на основе значения внешнего ключа зависимого объекта, находящегося на момент загрузки в памяти:
В независимом сопоставлении связанный конечный элемент зависимого объекта запрашивается на основе значения внешнего ключа зависимого объекта, находящегося на момент загрузки в базе данных. Однако если связь была изменена, а ссылочное свойство зависимого объекта указывает на другой объект Principal, загруженный в контекст объекта, Entity Framework попытается создать связь, как определено на клиенте.
Внешний ключ
С помощью API Fluent можно настроить, какое свойство следует использовать в качестве свойства внешнего ключа для данной связи:
Api Fluent можно использовать для настройки свойств составного внешнего ключа для данной связи:
Заметки к данным можно использовать для настройки свойства внешнего ключа для данной связи. Обычно это делается, если свойство внешнего ключа не обнаруживается по соглашению:
Заметку [ForeignKey] можно поместить в любое свойство навигации в связи. Не нужно переходить к свойству навигации в зависимом классе сущностей.
Свойство, указанное в [ForeignKey] свойстве навигации, не требуется существовать в зависимом типе. В этом случае указанное имя будет использоваться для создания теневого внешнего ключа.
Теневой внешний ключ
Вы можете использовать строковую перегрузку HasForeignKey(. ) для настройки свойства тени в качестве внешнего ключа (дополнительные сведения см. в разделе "Свойства тени "). Мы рекомендуем явно добавить свойство тени в модель, прежде чем использовать его в качестве внешнего ключа (как показано ниже).
Имя ограничения внешнего ключа
По соглашению при выборе реляционной базы данных ограничения внешнего ключа именуются FK___foreign key property name_. Для составных внешних ключей свойства внешнего ключа становится разделенным списком имен свойств внешнего ключа подчеркивания.
Можно также настроить имя ограничения следующим образом:
Настройка вручную
Чтобы настроить связь в API Fluent, сначала определите свойства навигации, составляющие связь. HasOne или HasMany идентифицирует свойство навигации для типа сущности, на котором начинается конфигурация. Затем выполняется цепочка вызовов WithOne и WithMany определение обратной навигации. HasOne / WithOne используются для ссылочных свойств навигации и HasMany / WithMany используются для свойств навигации коллекции.
Заметки к данным можно использовать для настройки связывания свойств навигации по зависимым и основным сущностям. Обычно это делается при наличии нескольких пар свойств навигации между двумя типами сущностей.
Свойства зависимой сущности можно использовать только для [Обязательного], чтобы повлиять на необходимость связи. [Обязательный] для навигации из основной сущности обычно игнорируется, но это может привести к тому, что сущность станет зависимой.
4 ответа
У вас есть два варианта: - без кавычек: тогда все будет автоматически вводиться строчными буквами и без учета регистра - с кавычками: теперь все чувствительно к регистру.
Я настоятельно рекомендую НЕ использовать кавычки и заставить PostgreSQL вести себя без учета регистра. это делает жизнь намного проще. как только вы перейдете к цитированию, вам нужно будет использовать его ВЕЗДЕ, поскольку PostgreSQL станет очень точным.
Действительно постарайтесь любой ценой избежать подобных уловок. оставайтесь с 7-битным ascii для имен объектов.
В моем случае. таблица в базе данных должна быть в нижнем регистре . изменить имя dataTable do datatable help
Строковая функция, используемая для подходящего цитирования идентификаторов в строке оператора SQL, - это >, который ссылается на хороший пример (используется вместе со связанным quote_literal() ).
Чтобы использовать ваш пример и смешать с другими результатами:
При использовании пакета npg в качестве ORM хранилища данных вы ожидаете, что структура ORM (Entity Framework в нашем случае) сгенерирует оператор sql, вы можете столкнуться с исключением PostgreSQL, отношение `` Имя таблицы '' не существует
Либо таблица не создана, либо в сгенерированном операторе SQL что-то отсутствует. Попробуйте отладить с помощью Visual Studio, вы увидите, что имя схемы не предшествует имени таблицы.
В то время как PostgreSQL ожидает имя схемы. Решение находится в классе DBContext, переопределите метод OnModelCreating и добавьте modelBuilder.HasDefaultSchema("SchemaName"); и выполните базовый конструктор, который должен выглядеть следующим образом
У меня уже есть записи для EntityB в базе данных. Я хочу добавить новый EntityA со ссылкой на одну из записей EntityB .
Когда приведенный выше код запускается, я получаю следующую ошибку:
System.InvalidOperationException: свойство Id для типа сущности EntityB является частью ключа и поэтому не может быть изменено или помечено как измененное. Чтобы изменить принципала существующей сущности с помощью идентифицирующего внешнего ключа, сначала удалите зависимого и вызовите SaveChanges, а затем свяжите зависимого с новым участником.
Мне кажется, что сохранение пытается также добавить EntityB , а не просто ссылку на него. У меня есть отношения, указанные в базе данных, а также в Entity Framework, например. при запросе EntityA , если я включаю EntityB в выбор, я также получаю ссылочный объект (так что связь работает).
Как я могу сохранить новый EntityA только со ссылкой на выбранный EntityB , а не сохранять оба объекта?
Одно свойство навигации
Включение только одного свойства навигации (без обратной навигации и отсутствие свойства внешнего ключа) достаточно для того, чтобы иметь связь, определенную соглашением. Вы также можете иметь одно свойство навигации и свойство внешнего ключа.
Настройка или сопоставление связей
В оставшейся части этой страницы описывается, как получить доступ к данным и управлять ими с помощью связей. Сведения о настройке связей в модели см. на следующих страницах.
- сведения о настройке связей в Code First см. в разделе аннотации данных и Fluent API — связи.
- Сведения о настройке связей с помощью Entity Framework Designer см. в разделе связи с конструктором EF.
Каскадное удаление
По соглашению каскадное удаление будет иметь значение Cascade для необходимых связей и ClientSetNull для необязательных связей. Каскад означает, что зависимые сущности также удаляются. ClientSetNull означает, что зависимые сущности, которые не загружаются в память, останутся неизменными и должны быть удалены вручную или обновлены, чтобы указать на действительную сущность субъекта. Для сущностей, загруженных в память, EF Core попытается задать для свойств внешнего ключа значение NULL.
Дополнительные сведения о различных способах удаления и значениях по умолчанию, используемых в соглашении, см. в статье "Каскадное удаление ".
Связи в EF
В реляционных базах данных связи (также называемые связями) между таблицами определяются через внешние ключи. Внешний ключ (FK) — это столбец или сочетание столбцов, которое применяется для принудительного установления связи между данными в двух таблицах. Обычно существует три типа связей: один к одному, один ко многим и многие ко многим. В связи «один ко многим» внешний ключ определяется в таблице, которая представляет собой множество элементов связи. Связь «многие ко многим» включает определение третьей таблицы (которая называется соединением или связующей таблицей), первичный ключ которых состоит из внешних ключей из обеих связанных таблиц. В связи «один к одному» первичный ключ действует в качестве внешнего ключа и не имеет отдельного внешнего ключевого столбца для любой таблицы.
На следующем рисунке показаны две таблицы, участвующие в связи «один ко многим». Таблица Course является зависимой таблицей, так как она содержит столбец DepartmentID , связывающий его с таблицей отдела .
В Entity Framework сущность может быть связана с другими сущностями через ассоциацию или связь. Каждая связь содержит две конечные точки, описывающие тип сущности и кратность типа (один, ноль или один или несколько) для двух сущностей в этой связи. Отношение может управляться справочным ограничением, описывающим, какой из конечных элементов отношения относится к основной роли, а какой к зависимой роли.
Свойства навигации обеспечивают способ навигации по ассоциации между двумя типами сущностей. Каждый объект может обладать свойством навигации для каждого отношения, в котором участвует. Свойства навигации позволяют перемещать связи и управлять ими в обоих направлениях, возвращая либо ссылочный объект (если кратность — либо одна, либо нулевая или-одна), либо коллекция (если количество элементов равно многим). Вы также можете выбрать односторонний переход. в этом случае вы определяете свойство навигации только для одного из типов, участвующих в связи, а не для обеих.
Рекомендуется включать в модель свойства, которые сопоставляются с внешними ключами в базе данных. Включение свойств внешних ключей позволяет создавать или изменять отношение, изменяя значение внешнего ключа для зависимого объекта. Сопоставление такого типа называется сопоставлением на основе внешнего ключа. Использование внешних ключей еще более важно при работе с отключенными сущностями. Обратите внимание, что при работе с 1-1 или 1 на-0. 1 связи нет отдельного внешнего ключевого столбца, свойство первичного ключа выступает в качестве внешнего ключа и всегда включается в модель.
Если внешние ключевые столбцы не включены в модель, сведения о взаимосвязих управляются как независимый объект. Отношения отправляются через ссылки на объекты, а не на внешние ключевые свойства. Этот тип связи называется независимой ассоциацией. Наиболее распространенным способом изменения независимой ассоциации является изменение свойств навигации, создаваемых для каждой сущности, участвующей в ассоциации.
В модели можно использовать один или оба типа сопоставлений. Однако если у вас есть отношение "многие ко многим", которое соединено таблицей соединения, содержащей только внешние ключи, EF будет использовать независимую ассоциацию для управления связью "многие ко многим".
На следующем рисунке показана концептуальная модель, созданная с помощью Entity Framework Designer. Модель содержит две сущности, участвующие в связи "один ко многим". Обе сущности имеют свойства навигации. Курс является зависимой сущностью и имеет определенное свойство внешнего ключа DepartmentID .
В следующем фрагменте кода показана та же модель, которая была создана с помощью Code First.
Одно свойство навигации
Если у вас есть только одно свойство навигации, то существуют перегрузки WithOne без параметров и WithMany . Это означает, что существует концептуальная ссылка или коллекция в другом конце связи, но в классе сущностей нет свойства навигации.
3 ответа
Для однозначных отношений EF ожидает, что в таблицах используется один и тот же первичный ключ. И действительно, если это действительно один на один, им, вероятно, следует . Итак, в вашем примере, если вы сделаете UserID первичным ключом в таблице UserProfiles, ваш индивидуальный подход будет работать.
У меня возникла эта проблема при попытке установить отношение 0..1 к 1 между основной таблицей и таблицей расширений. Таблица расширения, как и многие другие отношения, поэтому я не хочу связываться с PK этого. Есть идеи, как разрешить такую ситуацию?
@junior: это отношение внешнего ключа, и вы можете получить его, выбрав отношение, зайдя в свойства и изменив настройки «End1 Multiplicity» и «End2 Multiplicity» (хотя не уверен, что это только VS 2010). Скорее всего, вы установите "End2 Multiplicity" на "0..1".
Не существует «должен» , даже если EF не может правильно обрабатывать нормальные множественности RA и, таким образом, вынуждает изменить совершенно хороший дизайн RA. Это не подразумевает , что модель должна быть изменена, не говоря уже о текущем случае - означает, что EF, который все еще кажется сломанным сегодня, должен быть исправлен для правильного моделирования базы данных RA. домен.
Я был очень осторожен в своем ответе и придерживаюсь принципа «вероятно, должен» (я согласен с тем, что избегаю абсолютных положений и запретов, поэтому я осторожен в таких вещах). Тем не менее, я согласен с тем, что было бы полезно, если бы EF приспособил вариант использования, не требуя, чтобы он использовал тот же ключ.
Акцент очень важен. «Должен» - это фильтрация ограничений EF (которые довольно серьезны, поскольку он только учитывает мощность за пределами PK), а не RA или его реализации SQL. Хотя я согласен с тем, что этот случай может привести к простому изменению схемы, это не всегда возможно - или правильно с учетом FD. Подход с изгибом к EF избегает значительной части RA, даже если предоставлены действительные FK.
У меня аналогичная проблема, но со сценарием распродажи и простоя.
Непрофессионал может существовать без продажи, а продажа может существовать без посредника. Это означает, что у меня отношение 0 или 1 к 0 или 1 .
Layby ссылается на продажу, но Layby не может использовать первичный ключ Sale, а Sale не может использовать первичный ключ Layby.
Я решил проблему с помощью отношения 0 или 1 к многие , настроил геттер и сеттер Laybys для продажи как частные, а затем предоставил свой собственный Layby геттер и сеттер в моем POCO.
У меня возникла эта странная проблема с использованием PostgreSQL 9.3 с таблицами, созданными с использованием qoutes. Например, если я создаю таблицу с использованием кавычек:
Таблица создана правильно, и я вижу, что кавычки сохраняются при просмотре ее на панели SQL pgAdminIII. Но когда я запрашиваю БД, чтобы найти список всех доступных таблиц (используя запрос ниже), я вижу, что результат не содержит кавычек вокруг имени таблицы.
Поскольку таблица была создана с кавычками, я не могу использовать имя таблицы, возвращенное из приведенного выше запроса, напрямую, поскольку оно не заключено в кавычки и вызывает ошибку, размещенную в заголовке.
Я мог бы попробовать заключить имена таблиц в кавычки во всех запросах, но я не уверен, будет ли это работать все время. Я ищу способ получить список имен таблиц, которые в результате заключены в кавычки.
У меня такая же проблема с именами столбцов, но я надеюсь, что если я смогу найти решение проблемы с именами таблиц, аналогичное решение будет работать и для имен столбцов.
"Много ко многим"
Для связей "многие ко многим" требуется свойство навигации по коллекции с обеих сторон. Они будут обнаружены по соглашению, как и другие типы отношений.
Способ реализации этой связи в базе данных — таблица соединения, содержащая внешние ключи для обоих Post и Tag . Например, это то, что EF создаст в реляционной базе данных для приведенной выше модели.
Во внутренней среде EF создает тип сущности для представления таблицы соединения, которая будет называться типом сущности соединения. Dictionary в настоящее время используется для обработки любого сочетания свойств внешнего ключа, см. дополнительные сведения о типах сущностей контейнера свойств . В модели может существовать несколько связей "многие ко многим", поэтому тип сущности соединения должен иметь уникальное имя в данном случае PostTag . Эта функция называется типом сущности общего типа.
Тип CLR, используемый для типов сущностей соединения по соглашению, может измениться в будущих выпусках, чтобы повысить производительность. Не зависит от типа Dictionary соединения, если это не было явно настроено, как описано в следующем разделе.
Переходы "многие ко многим" называются пропусками навигаций, так как они фактически пропускают тип сущности соединения. Если вы используете массовую конфигурацию, все переходы по пропуску можно получить из GetSkipNavigations.
Присоединение к конфигурации типа сущности
Обычно конфигурация применяется к типу сущности соединения. Это действие можно выполнить с помощью UsingEntity .
Начальные данные модели можно предоставить для типа сущности соединения с помощью анонимных типов. Вы можете изучить представление отладки модели, чтобы определить имена свойств, созданные по соглашению.
Дополнительные данные можно хранить в типе сущности соединения, но для этого лучше создать тип CLR. При настройке связи с пользовательским типом сущности соединения необходимо явно указать оба внешних ключа.
Конфигурация объединения связей
EF использует две связи "один ко многим" в типе сущности соединения для представления связи "многие ко многим". Эти связи можно настроить в UsingEntity аргументах.
Возможность настройки связей "многие ко многим" появилась в EF Core 5.0 для предыдущей версии используйте следующий подход.
Косвенные связи "многие ко многим"
Можно также представить связь "многие ко многим", просто добавив тип сущности соединения и сопоставив две отдельные связи "один ко многим".
Поддержка формирования шаблонов для связей "многие ко многим" из базы данных еще не добавлена. Отслеживайте решение этого вопроса здесь.
Управление параллелизмом
Как в внешних, так и в независимых ассоциациях проверки параллелизма основываются на ключах сущностей и других свойствах сущности, определенных в модели. При использовании конструктора EF для создания модели присвойте ConcurrencyMode атрибуту значение fixed , чтобы указать, что свойство должно быть проверено на наличие параллелизма. при использовании Code First для определения модели используйте ConcurrencyCheck заметку для свойств, которые необходимо проверить на наличие параллелизма. при работе с Code First можно также использовать TimeStamp заметку, чтобы указать, что свойство должно проверяться на параллелизм. В данном классе может быть только одно свойство timestamp. Code First сопоставляет это свойство с полем базы данных, не допускающим значения null.
При работе с сущностями, участвующими в проверке и разрешении параллелизма, рекомендуется всегда использовать связь по внешнему ключу.
Дополнительные сведения см. в разделе Обработка конфликтов параллелизма.
Нет свойства внешнего ключа
Хотя рекомендуется иметь свойство внешнего ключа, определенное в зависимом классе сущностей, это не обязательно. Если свойство внешнего ключа не найдено, свойство теневого внешнего ключа будет введено с именем или если навигация отсутствует в зависимом типе.
В этом примере внешний ключ тени заключается в BlogId том, что добавление имени навигации будет избыточным.
Если свойство с таким же именем уже существует, имя теневой свойства будет суффиксировано числом.
Создание и изменение связей
При взаимосвязи с внешним ключомсостояние зависимого объекта с EntityState.Unchanged состоянием изменяется на EntityState.Modified . В независимых отношениях изменение связи не приводит к обновлению состояния зависимого объекта.
В следующих примерах показано, как использовать свойства внешнего ключа и свойства навигации для связывания связанных объектов. С помощью ассоциаций внешнего ключа можно использовать любой из методов для изменения, создания или изменения связей. Для независимых сопоставлений нельзя использовать свойство внешнего ключа.
Путем присвоения нового значения свойству внешнего ключа, как показано в следующем примере.
Следующий код удаляет связь, присвоив внешнему ключу значение NULL. Обратите внимание, что свойство внешнего ключа должно допускать значение null.
Если ссылка находится в добавленном состоянии (в данном примере это объект Course), свойство навигации ссылки не будет синхронизировано с ключевыми значениями нового объекта до тех пор, пока не будет вызван метод SaveChanges. Синхронизация не выполняется, поскольку контекст объекта не содержит постоянных ключей для добавленных объектов, пока они не будут сохранены. Если необходимо полностью синхронизировать новые объекты, как только вы настроили связь, используйте один из следующих методов. *
С помощью присваивания нового объекта свойству навигации. Следующий код создает связь между курсом и department . Если объекты присоединены к контексту, то course объект также добавляется department.Courses в коллекцию, а соответствующее свойство course внешнего ключа объекта задается значением свойства ключа отдела.
Путем удаления или добавления объекта в коллекцию сущностей. Например, можно добавить объект типа Course в department.Courses коллекцию. Эта операция создает связь между определенным курсом и конкретным department . Если объекты присоединены к контексту, ссылка на отдел и свойство внешнего ключа в объекте Course будут установлены соответствующим образом department .
С помощью ChangeRelationshipState метода можно изменить состояние указанной связи между двумя объектами сущностей. Этот метод чаще всего используется при работе с N-уровневых приложениями и независимой ассоциацией (его нельзя использовать с Ассоциацией внешнего ключа). Кроме того, чтобы использовать этот метод, необходимо раскрывающийся список ObjectContext , как показано в примере ниже.
В следующем примере существует связь «многие ко многим» между преподавателями и курсами. ChangeRelationshipState При вызове метода и передаче EntityState.Added параметра сообщается SchoolContext о том, что между двумя объектами была добавлена связь.
Обратите внимание, что при обновлении (не просто добавлении) связи необходимо удалить старую связь после добавления новой.
Работа с перекрывающимися ключами
Перекрывающиеся ключи представляют собой составные ключи, некоторые из свойств в которых также являются частью другого ключа в сущности. Для независимых сопоставлений использовать перекрывающиеся ключи нельзя. Для изменения сопоставления на основе внешнего ключа, содержащей перекрывающиеся ключи, рекомендуется изменять значения внешнего ключа вместо использования ссылок на объекты.
Я попытался создать файл фреймворка Entity и получил данные из своей базы данных.
Были некоторые проблемы с отношениями, поэтому я начал настраивать их, но продолжал получать следующую ошибку для простых отношений один-к-одному
Ошибка 1 Ошибка 113: множественность недопустима в роли «UserProfile» в отношении «FK_UserProfiles_Users». Поскольку свойства зависимой роли не являются ключевыми, верхняя граница кратности зависимой роли должна быть *. myEntities.edmx 2024 г.
Таблица «Мои пользователи» состоит из некоторых других отношений «многие ко многим» с другими таблицами, но когда я пытаюсь установить отношения «один к одному» с другими таблицами, эта ошибка выскакивает.
Таблица пользователей
- ID пользователя
- Имя пользователя
- Электронное письмо
Таблица UserProfiles
- UserProfileID
- UserID (FK для таблицы пользователей)
- Место нахождения
- День рождения
Следующий совет относится только к настройке отношения 1: 1.
вы можете использовать Разделение таблиц по соображениям производительности (обычно это средний уровень производительности) или по соображениям безопасности. Но это также возникает, когда нам нужно расширить устаревшую схему новыми метаданными, и есть код, который мы не можем контролировать, который сломался бы, если бы мы просто добавили дополнительные поля в существующую таблицу.
Ваша настройка для этого в основном верна, за исключением того, что EntityA.Id не может допускать значения NULL, поскольку в качестве первичного ключа он должен иметь значение.
Если вы хотите, чтобы в EntityA существовали записи, которые НЕ имеют соответствующую запись в EntityB , вам необходимо использовать другой столбец Id в качестве первичного ключа для EntityA или внешнего ключа для EntityB
Затем вам нужно заполнить пробел с помощью поля EntityA.Id , отключив автоматически созданное поведение, чтобы оно принимало значение Id из EntityB :
Я, вероятно, пошел бы еще дальше и добавил свойство Reciprocating или Inverse Navigation в EntityB , это позволило бы нам использовать более свободное назначение стилей вместо использования _dbContext.Add() для добавления запись в базу данных:
С помощью конфигурации:
Это позволяет добавить в более свободном стиле:
Это приведет к сбоям, потому что вы используете PK EntityA в качестве FK для Entity B, что обеспечивает прямое отношение 1 к 1. Примером этого может быть что-то вроде Order и OrderDetails, которые содержат дополнительные сведения о конкретном заказе. Оба будут использовать «OrderId» в качестве своего PK, а OrderDetails использует его PK для связи со своим Order.
Обычно связь между EntityA и EntityB требует, чтобы столбец EntityBId в таблице EntityA служил в качестве FK. Это может быть свойство в сущности EntityA или оставленное как свойство Shadow (рекомендуется, если EntityA будет иметь свойство навигации EntityB). Используя приведенный выше пример с Order и OrderType, запись Order будет иметь OrderId (PK) и OrderTypeId ( FK) к типу заказа, с которым он связан.
Сопоставление для этого будет: (Свойство тени)
OrderType может быть назначен многим Orders, но у нас нет коллекции Orders для OrderType. Мы используем .HasForeignKey("EntityBId") для настройки свойства тени EntityBId в нашей таблице EntityA. В качестве альтернативы, если мы объявим свойство EntityBId в нашем EntityA:
Кстати, свойства навигации должны быть объявлены virtual . Даже если вы не хотите полагаться на ленивую загрузку (рекомендуется), это помогает гарантировать, что прокси EF для отслеживания изменений будут полностью поддерживаться, а ленивая загрузка, как правило, является лучшим условием для выполнения во время выполнения, чем выбрасывание исключений NullReferenceExceptions.
Связь определяет, как две сущности связаны друг с другом. В реляционной базе данных это представляется ограничением внешнего ключа.
Большинство примеров в этой статье используют связь "один ко многим" для демонстрации концепций. Примеры связей "один к одному" и "многие ко многим" см. в разделе "Другие шаблоны отношений " в конце статьи.
Настройка свойств навигации
Эта возможность появилась в EF Core 5.0.
После создания свойства навигации может потребоваться дополнительно настроить его.
Этот вызов нельзя использовать для создания свойства навигации. Он используется только для настройки свойства навигации, созданного ранее путем определения связи или соглашения.
Читайте также: