#c# #.net #database #entity-framework #entity-framework-core
#c# #.net #База данных #entity-framework #entity-framework-core
Вопрос:
У меня есть приложение с ядром Entity Framework с разными объектами в моем контексте, но есть два из них, для которых требуется отношение один к нулю или один. Мой способ сделать это и обеспечить проверку состоял в том, чтобы сделать что-то вроде следующего:
public class PurchasedPackage
{
public int Id { get; set; }
...
[ForeignKey(nameof(PurchasedPackageModifier))]
public int? PurchasedPackageModifierId { get; set; }
public virtual PurchasedPackageModifier PurchasedPackageModifier { get; set; }
}
И
public class PurchasedPackageModifier
{
public int Id { get; set; }
...
[Required]
[ForeignKey(nameof(PurchasedPackage))]
public int PurchasedPackageId { get; set; }
public virtual PurchasedPackage PurchasedPackage { get; set; }
...
}
Где PurchasedPackage
требуется и PurchasedPackageModifier
является необязательным. Указывая ForeignKey
атрибут с обеих сторон, я пытаюсь обеспечить целостность данных при сохранении в обеих таблицах, чтобы никто не создавал a PurchasedPackage
с несуществующим PurchasedPackageModifier
и наоборот.
Хотя это работает по мере необходимости, я получаю предупреждения в своих журналах, в которых указано следующее:
'PurchasedPackage.PurchasedPackageModifier' and 'PurchasedPackageModifier.PurchasedPackage' were separated into two relationships as ForeignKeyAttribute was specified on properties 'PurchasedPackageModifierId' and 'PurchasedPackageId' on both sides.
И
'PurchasedPackageModifier.PurchasedPackage' and 'PurchasedPackage.PurchasedPackageModifier' were separated into two relationships as ForeignKeyAttribute was specified on properties 'PurchasedPackageId' and 'PurchasedPackageModifierId' on both sides.
Мой вопрос: правильно ли я это делаю и должен ли я игнорировать эти предупреждения в данном конкретном случае или есть лучший способ добиться такого же поведения проверки / целостности?
Комментарии:
1.
Where PurchasedPackage is required and PurchasedPackageModifier is optional. By specifying ForeignKey attribute on both sides I'm trying to ensure data integrity across saves to both tables so nobody creates a PurchasedPackage with a non-existent PurchasedPackageModifier and vice versa.
Это немного противоречит мне, поэтому, если вы не можете создать одно без другого, тогда ничего не является необязательным, или я что-то упускаю?2. @cantSleepNow с помощью MSSQL создаются 2 FK, по одному для каждой таблицы. Что касается требуемого / необязательного вопроса — PurchasedPackage может иметь нулевой или один PurchasedPackageModifier , который, в свою очередь, не может существовать без PurchasedPackage . Можно создать / обновить PurchasedPackage без модификатора, но если модификатор указан, его следует проверить на целостность. Модификатор PurchasedPackageModifier всегда должен содержать PurchasedPackage, к которому он применяется.
3. Спасибо за разъяснение, я соответствующим образом отредактирую ответ
Ответ №1:
Этот вопрос о предупреждениях закрыт в апреле 2018 года. Теперь я попробовал ваши два класса с mysql (библиотека pomelo), и действительно, я получаю один FK. Поэтому, если это приемлемо для вас, вы можете игнорировать предупреждения (процитировать одного из разработчиков по этой ссылке на github)
Если вам действительно нужно «отношение один к нулю или один», то я бы сделал это следующим образом:
PurchasedPackage
не имеет FK toPurchasedPackageModifier
, под этим я подразумеваю удаление обоихint? PurchasedPackageModifierId
и свойства навигацииurchasedPackageModifier PurchasedPackageModifier
— это охватывает часть 1-0, где запись вPurchasedPackage
может существовать без соответствующегоPurchasedPackageModifier
существующегоPurchasedPackageModifier
имеет столбецPurchasedPackageId
, который является FK toPurchasedPackage
, а также уникальный индекс — это охватывает часть 1-1, где
Комментарии:
1. Я действительно хочу, чтобы один-ноль-или-один, проблема в том, что если я пропущу FK для PurchasedPackage, тогда можно сохранить объект PurchasedPackage с помощью PurchasedPackage. PurchasedPackageModifierId устанавливается в любое недопустимое значение, которое не соответствует ни одному существующему идентификатору в таблице PurchasedPackageModifier
2. отредактируйте ответ и после этого комментария. Первоначально, удаляя FK, я имел в виду, что вы удаляете как свойство int, так и свойство навигации.
3. Правильно ли я предполагаю, что мои 2 варианта либо имеют 2 FK, либо полностью удаляют доступ к PurchasedPackageModifier для PurchasedPackage?
4. Я не знаю, являются ли они единственными 2 🙂 Но 2 FKS в этом случае кажется немного странным. Может быть, посмотрите на варианты использования, описанные в моей идее: 1- У вас может быть a
PurchasedPacakge
, которого нетPurchasedPackageModifier
, и вы можете запрашивать такие записи. 2- Если у вас естьPurchasedPackageModifier
соответствующиеPurchasedPacakge
записи ahs, которые должны существовать (благодаря FK), и у него может быть только один из них (благодаря UniqueIDX), вы также можете запросить все PP, у которых есть PPM.5. Таким образом, вы не удаляете доступ, потому что таким образом доступ не требуется, если вы просто PP JOIN PPM, вы получите все PPS, у которых есть PPM, если вы делаете PP LEFT JOIN PPM, ГДЕ INSULL (PPM) (очевидно, псевдокод), вы можете получить все PPS, у которых нет PPM. Это все, что вам нужно. Поэтому ищите существование PPM, используя две таблицы вместо одной