Я создал веб-приложение asp.NET MVC с двумя моделями, использующими EF Code First, которые имеют отношение 1 к 0..1.Выполнение ссылочной целостности при удалении объекта в отношениях 1-к 0..1
public class ClassA
{
public int Id {get;set;}
//other properties
public virtual ClassB ClassB {get;set;}
}
public class ClassB
{
public int Id {get;set;}
//other properties
}
В моей базе данных это успешно создает две таблицы с ClassA с Nullable FK для ClassB. Это отлично работает, за исключением сценария, в котором удалена запись ClassA. В этом случае любая связанная запись ClassB остается в базе данных. Я знаю, что я могу вручную удалить их в методе POST Delete:
[HttpPost, ActionName("Delete")]
[ValidateAntiForgeryToken]
public ActionResult DeleteConfirmed(int id)
{
ClassA classA = context.ClassA.Include(c => c.ClassB).First(c => c.Id == id);
context.ClassB.Remove(classA.ClassB);
context.ClassA.Remove(classA);
context.SaveChanges();
}
мне не очень нравится этот подход, поскольку он опирается на меня не делает ошибку, и предполагается, что этот метод является единственным способом, что запись (в какой-то момент также могут быть указаны прямые инструкции DELETE SQL в отношении базы данных). Пример, который я создал здесь, прост, но мое фактическое приложение включает в себя множество моделей и ассоциаций, и оно стало довольно сложным. Хотя мне нравится думать, что я безошибочен, я по опыту узнал, что я не являюсь, и не буду полагаться на себя, чтобы гарантировать, что записи не становятся сиротами =)
Как заставить базу данных принудительно использовать ссылочный целостность, так что, когда ClassA удаляется, все ClassB, имеющие внешние ключи в этом ClassA, также удаляются?
РЕШИТЬ (своего рода)
Как было предложено Герт, я использовал Fluent API, чтобы гарантировать, что право объект был установлен как принцип и установить все отношения каскадом на удаление. Однако я столкнулся с несколькими проблемами, в основном из-за того, что в моей базе данных уже есть данные. К счастью, я нахожусь в разработке, где я могу просто удалить все данные; в противном случае, я не уверен, как бы я это исправил.
Сначала я попытался просто добавить Fluent API и базу данных обновлений. Я получил ошибку, которая частично читается: «Либо параметр @objname неоднозначен, либо заявленный код @objtype (COLUMN) ошибочен», который, по-видимому, вызван тем, что EF пытается изменить имя существующего столбца FK. В этом случае я решил использовать 2 миграции: один для удаления существующих отношений, а другой - для добавления вновь переконфигурированных отношений. Я должен был сделать это в довольно определенной серии событий.
- Прокомментировал все ссылки на затронутые отношения в моем контроллере, чтобы избежать ошибок при обновлении.
Прокомментировал связь в Модели.
public class ClassA { public int Id {get;set;} //other properties //public virtual ClassB ClassB {get;set;} }
- Add-Migration and Update-Database, чтобы удалить существующие отношения.
- расстегнул все изменения в модель и контроллер раскомментировав все, что я комментировал в шаге 1 и 2.
Настроенного новые отношения в OnModelCreating как это было предложено Гертом, чтобы сохранить новые отношения.
modelBuilder.Entity<ClassA>() .HasOptional(b => b.ClassB) .WithRequired() .Map(m => m.MapKey("ClassB_Id")) .WillCascadeOnDelete();
Add-Migration and Update-Database для создания новых отношений. Этот шаг не удался, когда в моей базе данных были данные. Если бы у меня не было возможности просто очистить базу данных всех данных, я не уверен, как бы я это сделал.
Спасибо за помощь! Это работало до тех пор, пока у меня не было данных уже в затронутых таблицах в базе данных. К счастью, я нахожусь в разработке, где я могу просто очистить базу данных для запуска этого обновления, но как я мог бы это сделать, если бы мне пришлось поддерживать существующие данные? – IamzombieGrrArgh
Трудно сказать отсюда. Честно говоря, у меня нет практического опыта миграции, я всегда, кажется, в конечном итоге работаю с базой данных. В любом случае, похоже, вы узнали, как это сделать. –