Zmagam się z tym od dłuższego czasu i nie mogę do końca zrozumieć, co się dzieje. Mam encję Karty, która zawiera Strony (zwykle 2) - a obie Karty i Strony mają scenę. Korzystam z migracji EF Codefirst i migracje kończą się niepowodzeniem z powodu tego błędu:
Wprowadzenie ograniczenia OBCEGO KLUCZA „FK_dbo.Sides_dbo.Cards_CardId” w tabeli „Strony” może powodować cykle lub wiele ścieżek kaskadowych. Określ NA USUŃ BRAK AKCJI lub NA AKTUALIZACJĘ BEZ AKCJI, lub zmodyfikuj inne KLUCZE OBCE.
Oto moja karta Card :
public class Card
{
public Card()
{
Sides = new Collection<Side>();
Stage = Stage.ONE;
}
[Key]
[Required]
public virtual int CardId { get; set; }
[Required]
public virtual Stage Stage { get; set; }
[Required]
[ForeignKey("CardId")]
public virtual ICollection<Side> Sides { get; set; }
}
Oto moja jednostka Side :
public class Side
{
public Side()
{
Stage = Stage.ONE;
}
[Key]
[Required]
public virtual int SideId { get; set; }
[Required]
public virtual Stage Stage { get; set; }
[Required]
public int CardId { get; set; }
[ForeignKey("CardId")]
public virtual Card Card { get; set; }
}
A oto moja jednostka Stage :
public class Stage
{
// Zero
public static readonly Stage ONE = new Stage(new TimeSpan(0, 0, 0), "ONE");
// Ten seconds
public static readonly Stage TWO = new Stage(new TimeSpan(0, 0, 10), "TWO");
public static IEnumerable<Stage> Values
{
get
{
yield return ONE;
yield return TWO;
}
}
public int StageId { get; set; }
private readonly TimeSpan span;
public string Title { get; set; }
Stage(TimeSpan span, string title)
{
this.span = span;
this.Title = title;
}
public TimeSpan Span { get { return span; } }
}
Dziwne jest to, że jeśli dodam następujące elementy do mojej klasy Stage:
public int? SideId { get; set; }
[ForeignKey("SideId")]
public virtual Side Side { get; set; }
Migracja przebiega pomyślnie. Jeśli otworzę SSMS i spojrzę na tabele, widzę, że Stage_StageId
został dodany do Cards
(zgodnie z oczekiwaniami / pożądaniami), jednak Sides
nie zawiera odniesienia do Stage
(nie oczekiwano).
Jeśli to dodam
[Required]
[ForeignKey("StageId")]
public virtual Stage Stage { get; set; }
public int StageId { get; set; }
Do mojej klasy Side widzę StageId
kolumnę dodaną do mojej Side
tabeli.
Działa to, ale teraz w mojej aplikacji każde odniesienie do Stage
zawiera SideId
, co w niektórych przypadkach jest całkowicie nieistotne. Chciałbym po prostu nadać mojemu Card
i Side
podmiotom Stage
właściwość opartą na powyższej klasie Stage bez zanieczyszczania klasy stage właściwościami referencyjnymi, jeśli to możliwe ... co robię źle?
Side
klasie dodaj Nullable integer i usuń[Required]
atrybut =>public int? CardId { get; set; }
DeleteBehavior.Restrict
lubDeleteBehavior.SetNull
.Odpowiedzi:
Ponieważ
Stage
jest to wymagane , wszystkie relacje jeden-do-wielu, w którychStage
jest zaangażowana, będą domyślnie włączone kaskadowe usuwanie. Oznacza to, że jeśli usunieszStage
jednostkęSide
Card
i ponieważCard
i będzieSide
mieć wymaganą relację jeden-do-wielu z domyślnie włączoną funkcją usuwania kaskadowego, a następnie kaskadowo odCard
doSide
Tak więc masz dwie kaskadowe ścieżki usuwania od
Stage
doSide
- co powoduje wyjątek.Musisz albo ustawić
Stage
opcję opcjonalną w co najmniej jednym obiekcie (tj. Usunąć[Required]
atrybut zStage
właściwości), albo wyłączyć kaskadowe usuwanie za pomocą Fluent API (nie jest to możliwe z adnotacjami danych):źródło
Stage
. Inne relacje pozostają niezmienione.Stage
Side
Card
Miałem stół, który miał okrągły związek z innymi i otrzymywałem ten sam błąd. Okazuje się, że chodzi o klucz obcy, który nie był zerowalny. Jeśli klucz nie ma wartości zerowej, obiekt powiązany musi zostać usunięty, a relacje cykliczne na to nie pozwalają. Więc użyj zerowego klucza obcego.
źródło
int?
zamiastint
pozwolić, aby był zerowalny.Każdy, kto zastanawia się, jak to zrobić w rdzeniu EF:
źródło
builder.HasOne(x => x.Stage).WithMany().HasForeignKey(x => x.StageId).OnDelete(DeleteBehavior.Restrict);
builder _ .Entity<TEntity>() _
wcześniejHasOne()
można je nazwać ...IEntityTypeConfiguration<T>
. Nie przypominam sobie, aby widziałem tębuilder.Entity<T>
metodę w tych dniach, ale mogę się mylić. Niemniej jednak oba będą działać :)Ten błąd pojawiał się w przypadku wielu jednostek podczas migracji z modelu EF7 do wersji EF6. Nie chciałem przechodzić przez każdą jednostkę pojedynczo, więc użyłem:
źródło
Możesz ustawić cascadeDelete na false lub true (w metodzie Up () migracji). Zależy od twoich wymagań.
źródło
UP
metoda może zostać zmodyfikowana przez operacje zewnętrzne.W .NET Core zmieniłem opcję onDelete na ReferencialAction.NoAction
źródło
Miałem również ten problem, rozwiązałem go natychmiast dzięki tej odpowiedzi z podobnego wątku
W moim przypadku nie chciałem usuwać zależnego rekordu po usunięciu klucza. Jeśli tak jest w twojej sytuacji, po prostu zmień wartość logiczną w migracji na false:
Szanse są, jeśli tworzysz relacje, które generują ten błąd kompilatora, ale NIE chcesz zachować kaskadowego usuwania; masz problem ze swoimi relacjami.
źródło
Naprawiłem to. Po dodaniu migracji w metodzie Up () pojawi się następujący wiersz:
Jeśli po prostu usuniesz cascadeDelete od końca, będzie działać.
źródło
Dla celów dokumentacyjnych, dla kogoś, kto przyjdzie w przyszłości, to można rozwiązać tak prosto, jak to, a dzięki tej metodzie możesz zrobić metodę, która została jednorazowo wyłączona, i możesz uzyskać normalny dostęp do tej metody
Dodaj tę metodę do klasy kontekstowej bazy danych:
źródło
Brzmi dziwnie i nie wiem dlaczego, ale w moim przypadku tak się stało, ponieważ mój ConnectionString używał „.” w atrybucie „źródło danych”. Gdy zmieniłem go na „localhost”, działało to jak urok. Żadna inna zmiana nie była potrzebna.
źródło
W .NET Core grałem ze wszystkimi górnymi odpowiedziami - ale bez powodzenia. Wprowadziłem wiele zmian w strukturze DB i za każdym razem dodawałem nową próbę migracji
update-database
, ale otrzymywałem ten sam błąd.Potem zacząłem
remove-migration
jeden po drugim, aż konsola Menedżera pakietów rzuciła mi wyjątek:Następnie dodałem nową migrację (
add-migration
) iupdate-database
pomyślnieTak więc moja sugestia brzmiałaby: wyczyść wszystkie migracje tymczasowe, aż do obecnego stanu bazy danych.
źródło
Istniejące odpowiedzi są świetne. Chciałem tylko dodać, że napotkałem ten błąd z innego powodu. Chciałem utworzyć początkową migrację EF na istniejącej bazie danych, ale nie użyłem flagi -IgnoreChanges i zastosowałem polecenie Aktualizuj bazę danych na pustej bazie danych (także w przypadku istniejących awarii).
Zamiast tego musiałem uruchomić tę komendę, gdy bieżąca struktura db jest aktualna:
Prawdopodobnie istnieje prawdziwy problem w strukturze db, ale ratuj świat krok po kroku ...
źródło
Prostym sposobem jest, edytować plik migracji
(cascadeDelete: true)
na(cascadeDelete: false)
to po przypisać polecenie Update-bazy danych w menedżerze pakietów Console.if Jest problem z ostatniej migracji ówczesnego porządku. W przeciwnym razie sprawdź swoją wcześniejszą historię migracji, skopiuj te rzeczy, wklej do ostatniego pliku migracji, a następnie zrób to samo. to doskonale dla mnie działa.źródło
Gdy migracja się nie powiedzie, pojawi się kilka opcji: „Wprowadzenie ograniczenia KLUCZ ZAGRANICZNY” FK_dbo.ZalecanyBook_dbo.Department_DepartmentID ”w tabeli„ RecommendedBook ”może powodować cykle lub wiele ścieżek kaskadowych. Określ NA USUŃ BRAK AKCJI lub NA AKTUALIZACJĘ BEZ AKCJI, lub zmodyfikuj inne ograniczenia KLUCZA OBCYCH. Nie można utworzyć ograniczenia ani indeksu. Zobacz poprzednie błędy. ”
Oto przykład użycia opcji „modyfikuj inne KLUCZE OBCE” poprzez ustawienie „cascadeDelete” na wartość false w pliku migracji, a następnie uruchomienie „update-database”.
źródło
Żadne z wyżej wymienionych rozwiązań nie działało dla mnie. Musiałem użyć wartości zerowej int (int?) Na kluczu obcym, który nie był wymagany (lub klucza innej niż null), a następnie usunąć niektóre z moich migracji.
Najpierw usuń migracje, a następnie wypróbuj wartość zerową int.
Problem dotyczył zarówno modyfikacji, jak i projektu modelu. Zmiana kodu nie była konieczna.
źródło
Ustaw atrybuty klucza obcego na wartości zerowe. To zadziała.
źródło