#c# #sql-server #database #entity-framework-core #dbcontext
#c# #sql-сервер #.net-core #entity-framework-core #dbcontext
Вопрос:
Ребята, я пытаюсь запустить dotnet ef database update
command, но во время ее выполнения у меня возникает исключение:
Failed executing DbCommand (12ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
CREATE TABLE [ProductSubCategory] (
[ProductId] int NOT NULL,
[SubCategoryId] int NOT NULL,
CONSTRAINT [PK_ProductSubCategory] PRIMARY KEY ([SubCategoryId], [ProductId]),
CONSTRAINT [FK_ProductSubCategory_Product_ProductId] FOREIGN KEY ([ProductId]) REFERENCES [Product] ([ProductId]) ON DELETE CASCADE,
CONSTRAINT [FK_ProductSubCategory_SubCategory_SubCategoryId] FOREIGN KEY ([SubCategoryId]) REFERENCES [SubCategory] ([SubCategoryId]) ON DELETE CASCADE
);
Microsoft.Data.SqlClient.SqlException (0x80131904): Introducing FOREIGN KEY constraint 'FK_ProductSubCategory_SubCategory_SubCategoryId' on table 'ProductSubCategory' may cause cycles or multiple cascade paths. Specify ON DELETE NO ACTION or ON UPDATE NO ACTION, or modify other FOREIGN KEY constraints.
Could not create constraint or index. See previous errors.
Introducing FOREIGN KEY constraint 'FK_ProductSubCategory_SubCategory_SubCategoryId' on table 'ProductSubCategory' may cause cycles or multiple cascade paths. Specify ON DELETE NO ACTION or ON UPDATE NO ACTION, or modify other FOREIGN KEY constraints.
Could not create constraint or index. See previous errors.
Я использую Sql Server в качестве поставщика базы данных и Entity framework core 3.19 в моем ASP.NET ОСНОВНОЕ приложение MVC. Честно говоря, я не уверен, что является ее причиной, поскольку раньше у меня не было таких проблем, они появились, как только я добавил свойства внешнего ключа, например, public int CategoryId { get; set; }
для всех зависимых объектов (для отношений «один ко многим»), таких как Product, потому что я забыл добавить их раньше, и теперь я буду использовать их вдля обновления объектов продукта.Я показываю сущности и свободный код api
Product.cs
public class Product
{
public int ProductId { get; set; }
public string Name { get; set; }
public double Price { get; set; }
public Category Category { get; set; }
public int CategoryId { get; set; } //It's one of the foreign keys properties added
public Brand Brand { get; set; }
public int BrandId { get; set; } //It's one of the foreign keys properties added
public string ImageName { get; set; }
public IEnumerable<ProductSubCategory> SubCategories { get; set; }
}
ProductSubCategory.cs
public class ProductSubCategory
{
public int ProductId { get; set; }
public Product Product { get; set; }
public int SubCategoryId { get; set; }
public SubCategory SubCategory { get; set; }
}
SubCategory.cs
public class SubCategory
{
public int SubCategoryId { get; set; }
public string Name { get; set; }
public int CategoryId { get; set; }
public Category Category { get; set; }
[JsonIgnore]
public IEnumerable<ProductSubCategory> ProductSubCategories { get; set; }
}
Category
public class Category
{
public int CategoryId { get; set; }
public string Name { get; set; }
public IEnumerable<Product> Products { get; set; }
public IEnumerable<SubCategory> SubCategories { get; set; }
}
DbContext.cs
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<ProductSubCategory>()
.HasKey(psc => new {psc.SubCategoryId, psc.ProductId});
modelBuilder.Entity<ProductSubCategory>()
.HasOne(psc => psc.Product)
.WithMany(p => p.SubCategories)
.HasForeignKey(psc => psc.ProductId);
modelBuilder.Entity<ProductSubCategory>()
.HasOne(psc => psc.SubCategory)
.WithMany(sc => sc.ProductSubCategories)
.HasForeignKey(psc => psc.SubCategoryId);
}
Я почти уверен, что правильно настроил связь.
Вещи, которые я пробовал:
- Удалите папку миграции и создайте новую.
- Обновите пакет nuget ядра Ef до последней версии
- Удаление базы данных, а затем создание новой.
PD: Пожалуйста, мне нужна помощь, у меня нет времени, если вам нужен исходный код проекта entities с соответствующим Dbcontext, я могу предоставить его вам, но, как я уже сказал, он содержит 19 классов сущностей.
Это исходный код: https://github.com/ToastedGuy2/Food-Town-issue
РЕДАКТИРОВАТЬ: реальный вопрос заключался в том, как удалить On Cascade On Delete
в каждом внешнем ключе? Не имеет значения, является ли это отношением «Один ко многим» или «Многие ко многим».
Комментарии:
1. Ошибка сообщает вам о проблеме: «Введение ограничения ВНЕШНЕГО КЛЮЧА ‘FK_ProductSubCategory_SubCategory_SubCategoryId’ в таблицу ‘ProductSubCategory’ может вызвать циклы или несколько каскадных путей. Укажите ПРИ УДАЛЕНИИ НИКАКИХ ДЕЙСТВИЙ или ПРИ ОБНОВЛЕНИИ НИКАКИХ ДЕЙСТВИЙ или измените другие ограничения ВНЕШНЕГО КЛЮЧА».
2. Какая часть? Ошибка вполне понятна и явно указана в решении.
3. Не для меня, я многое забыл о базе данных, это первый раз, я сталкиваюсь с этим. Пожалуйста, можете ли вы предоставить мне решение для этого?
4. Просто найдите SO для «циклов или нескольких каскадных путей»
5. Хорошо, давайте начнем, что не имеет смысла для утверждения «может вызывать циклы или несколько каскадных путей» ? Затем, после этого, какая часть «Указать ПРИ УДАЛЕНИИ НИКАКИХ ДЕЙСТВИЙ или ПРИ ОБНОВЛЕНИИ НИКАКИХ ДЕЙСТВИЙ или изменить другие ограничения ВНЕШНЕГО КЛЮЧА». вы не понимаете? Какие конкретные части вас смущают?
Ответ №1:
Введение ограничения ВНЕШНЕГО КЛЮЧА ‘FK_ProductSubCategory_SubCategory_SubCategoryId’ в таблице ‘ProductSubCategory’ может вызвать циклы или несколько каскадных путей. Укажите, ЧТО ПРИ УДАЛЕНИИ НЕТ ДЕЙСТВИЯ или ПРИ ОБНОВЛЕНИИ НЕТ ДЕЙСТВИЯ, или измените другие ограничения ВНЕШНЕГО КЛЮЧА.
Ошибка буквально говорит вам о проблеме здесь. Я не уверен, какой бит неясен, поскольку в OP указано, что они ничего из этого не понимают (что, я должен признать, подразумевает языковой барьер, и поэтому я предлагаю изменить ваш язык LOGIN
, чтобы получить ошибку на языке, с которым вы более знакомы), однако я буду слишком «тупым»это вниз:
Ввод ограничения ВНЕШНЕГО КЛЮЧА ‘fk_productsubcategory_subcategory_subcategory_subcategoryid’
Речь идет о FOREIGN KEY
том, что вы пытаетесь создать вызываемый FK_ProductSubCategory_SubCategory_SubCategoryId
в таблице «ProductSubCategory»
Это говорит вам о том, что вышеупомянутое FOREIGN KEY
пытается быть создано в таблице ProductSubCategory
может вызвать циклы или несколько каскадных путей.
Это означает, что вышеупомянутый FOREIGN KEY
, который пытается быть создан на вышеупомянутом TABLE
, вызовет циклы или несколько каскадных путей.
- Цикл будет означать, что
DELETE
вызовет дальнейшие удаления в той же таблице, вызывая больше удалений в той же таблице, вызывая больше удалений в той же таблице, … вызывая больше удалений в той же таблице, … (Вы поняли идею) - Множественные каскадные пути означают, что будет несколько других таблиц, из которых будут удалены строки, что теперь разрешено в SQL Server; особенно если они позже сойдутся в одной таблице.
Укажите ПРИ УДАЛЕНИИ НИКАКИХ ДЕЙСТВИЙ или ПРИ ОБНОВЛЕНИИ НИКАКИХ ДЕЙСТВИЙ
Я действительно не знаю, как это уточнить. Вместо ON CASCADE
использования NO ACTION
. Иначе, обработайте каскадирование самостоятельно.
или измените другие ограничения ВНЕШНЕГО КЛЮЧА
Опять же, это очень много говорит вам, что делать. Измените другие CONSTRAINT
файлы в вашей таблице, чтобы они не вызывали цикл или несколько путей; вероятно, необходимо изменить этот ключ NO ACTION
и передать каскадирование самостоятельно.
Комментарии:
1. Спасибо, что уделили мне время. Как мне указать ПРИ удалении НИКАКИХ действий ? Потому что я заметил, что они есть во всем проекте, и, честно говоря, у него их не должно быть, поэтому я в основном должен сообщить ef core, чтобы удалить его, но как? Просто чтобы предоставить больше контекста, в моем проекте я не удаляю записи, я просто отключаю их с помощью логического свойства isItActive .
2. Вопрос: Как ядро EF узнает, есть ли внешний ключ
ON DELETE CASCADE OR NO ACTION
. Поскольку в отношениях «многие ко многим» он добавлен по умолчанию, я просто следовал соглашению, как говорилось на других страницах. Когда дело доходит до отношения один ко многим, я следовал этому соглашению # 4 этой страницы: entityframeworktutorial.net/efcore/… . В основном это говорит: полное определение отношения на обоих концах с помощью свойства внешнего ключа в зависимом объекте создает отношение «один ко многим».
Ответ №2:
Попробуйте изменить
modelBuilder.Entity<ProductSubCategory>()
.HasOne(psc => psc.Product)
.WithMany(p => p.SubCategories)
.HasForeignKey(psc => psc.ProductId);
Для
modelBuilder.Entity<ProductSubCategory>()
.HasOne(psc => psc.Product)
.WithMany(p => p.ProductSubCategories)
.HasForeignKey(psc => psc.ProductId);
И я обычно использую .OnDelete(удалить поведение.ClientSetNull)
Комментарии:
1. Серж, свойство SubCategories в основном содержит список ProductSubCategories . Итак, я не понимаю, откуда у вас ProductSubCategories . Думаю, мне следует снова переименовать свойства, чтобы было понятнее.
2. Следующая запись в вашем коде ModelBuilder . Сущность<ProductSubCategory>() .hasOne(psc => psc.SubCategory) . С помощью Many(sc => sc.ProductSubCategories) . HasForeignKey(psc => psc.SubCategoryId);
3. Я имею в виду, что отношения хорошо настроены, мне просто нужно удалить все
ON DELETE CASCADE
из моих внешних ключей.4. Хорошо, я собираюсь попробовать.
Ответ №3:
По умолчанию в ядре EF используется каскадное удаление. Это начинает вызывать проблемы, когда у вас их слишком много, и вы все равно не хотите, чтобы они были повсюду.
При определении ваших отношений, вы должны попытаться по умолчанию не каскадировать самостоятельно, за исключением ситуаций, когда вы действительно хотите каскад.
entityBuilder
.HasMany(one => one.Many)
.WithOne(many => many.One)
.OnDelete(DeleteBehavior.NoAction);