ForeignKey SetNull OnDelete - PullRequest
1 голос
/ 24 мая 2019

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

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

Точность: я использую Entity Framework Core (последняя версия).

Ответы [ 3 ]

1 голос
/ 24 мая 2019

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

Другой столбец

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

Не определяйте внешний ключ для этой таблицы

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

Отключение проверки внешнего ключа

Это "решит" вашу проблему, но по возможности ее следует избегать.

Виртуальноудаление

В целевой таблице вы можете создать удаленный флаг и установить для него значение true вместо фактического удаления.

0 голосов
/ 11 июля 2019

Наконец, я переопределил метод SaveChanges, чтобы исследовать дочерние элементы, и установил для всей части столбца FK значение null (кроме TenantId).

Вот код, позволяющий выполнять итерацию по одному свойству сущностей навигации:

foreach (var navigationEntry in entry.Navigations
                            .Where(n => !n.Metadata.IsDependentToPrincipal()))
{
    if (navigationEntry is CollectionEntry collectionEntry)
    {
        // FK uses DeleteBehavior.ClientSetNull -> let's set it to NULL
        if (((Microsoft.EntityFrameworkCore.Metadata.Internal.Navigation)((MemberEntry)navigationEntry).Metadata).Builder.Metadata.ForeignKey.DeleteBehavior == DeleteBehavior.ClientSetNull)
        {
            // getting all fields composing the FK (except TenantId)
            List<string> fieldsToSetToNull = ((Microsoft.EntityFrameworkCore.Metadata.Internal.Navigation)((MemberEntry)navigationEntry).Metadata).Builder.Metadata.ForeignKey.Properties.Where(x => x.Name != nameof(IMustHaveTenant.TenantId)).Select(x => x.Name).ToList();

            List<object> dependentEntitiesList = new List<object>((IEnumerable<object>)collectionEntry.CurrentValue);
            for (var i = dependentEntitiesList.Count - 1; i >= 0; i--)
            {
                // setting all fields to NULL
                foreach (string fi in fieldsToSetToNull)
                {
                    var childEntry = this.Entry(dependentEntitiesList[i]);
                    childEntry.CurrentValues[fi] = null;
                }
            }
        }
    }
}


0 голосов
/ 24 мая 2019

Спасибо за ваш ответ.

Я согласен со всем, что вы сказали, кроме одного:

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

Тот факт, что один из столбцов имеет значение NULL (тот, который я хочу установить в NULL), позволяет мне сделать следующее FK {ParentId: null, TenantId: 4} не ссылается на строку. Если я установил ParentId, FK теперь ссылается на строку.

В моем случае я просто хочу, чтобы, если я удаляю Parent, только ParentId был установлен в null, а не TenantId, который используется для некоторых других FK, а также в PK. Но я пришел к такому же выводу, что вам это не представляется возможным ...

...