Mam doktorat. w cs - w obszarze Bazy danych, więc ta odpowiedź będzie nieco inna niż perspektywa programistów. Z całym szacunkiem dla Olivera Hanappiego, klucz może i czasami się zmienia, jeśli nie jest kluczem zastępczym. Np. Klucz naturalny lub klucz złożony. Na przykład. Istnieje możliwość zmiany numeru SSN w USA. Ale wielu programistów przez lata uważało ten klucz za niezmienny i używało go jako takiego. Znacznie częściej zmienia się złożony klucz podstawowy składający się z kluczy obcych.
Mam do czynienia z bazą danych, która ma relację trójskładnikową. W szczególności trzy jednostki (z kluczami obcymi będącymi zastępcami kluczy podstawowych w odpowiednich tabelach). Jednak, aby zachować relację między dwoma podmiotami podczas zmiany trzeciego podmiotu, wymaga zmiana części tabeli przecięcia (nazywanej również tabelą czystego sprzężenia w MSDN) klucz podstawowy. Jest to poprawny projekt i można go ulepszyć tylko przez usunięcie tabeli przecięcia relacji trójskładnikowych i zastąpienie jej dwiema tabelami relacji binarnych (które mogą mieć własne klucze zastępcze). EF poradzi sobie z tym dobrze. Ta zmiana projektu spowoduje utworzenie modelu (Wiele->wiele)->wiele lub Rodzic1-Rodzic2 -> Dziecko-wnuk (jeśli to nie jest jasne, przeczytaj poniższy przykład). Rama encji działałaby dobrze z tym, ponieważ każda relacja jest tak naprawdę relacją jeden do wielu. Ale to szalony projekt z perspektywy DB. Pokażę Ci przykład dlaczego.
Weź pod uwagę, że Kurs, Klasa i Instruktor są ze sobą powiązane w klasie. Klasa może zawierać:CourseID, ClassroomID, InstructorID jako klucze obce i zawierać złożony klucz podstawowy zawierający wszystkie trzy. Chociaż jest to jasny, zwięzły model trójskładnikowy (relacja 3-drożna), możemy podzielić go na relacje binarne. Dałoby to dwie tabele przecięcia. Dodanie kluczy zastępczych spełniałoby wymagania EF w następujący sposób:
Klasa(SurrogateKeyClass , Identyfikator instruktora , Identyfikator kursu )
ClassRoomUsed(SurrogateKeyClassroomUsed , SurrogateKeyClass , Identyfikator Klasy )
Problem z tym projektem polega na tym, że możemy wielokrotnie skojarzyć ten sam kurs i instruktora, czego unika poprzedni model. Aby uniknąć tego problemu, możesz dodać do bazy danych ograniczenie dotyczące unikalności dwóch pól identyfikatora, ale po co miałbyś to robić, skoro na początku masz do czynienia tylko z kluczami zastępczymi? Jednak to rozwiązanie działałoby najlepiej, jak mogę powiedzieć. Nie jest to jednak projekt logicznej bazy danych z powodu nienaturalnego ograniczenia unikalności wymaganego w DB.
ALE, jeśli nie chcesz zmieniać bazy danych lub nie możesz zmienić bazy danych, oto drugie rozwiązanie :Tabele przecięć/powiązań to tylko linki łączące ze sobą dwa lub więcej podmiotów. Jeśli coś się zmieni, usuń powiązanie i utwórz nowe, które ma odpowiednie klucze obce (właściwości nawigacji). Oznacza to, że nie będziesz mógł wymagać bytów podrzędnych w żadnej z relacji, ale jest to niezwykle powszechne.
Sugerowałbym, aby Entity Framework (w przyszłości) umożliwił tym z nas, którzy potrafią zaprojektować elegancki model DB, zmianę części kluczy w tabelach przecięcia/skojarzeń, kiedy tylko zechcemy!
Kolejny przykład za darmo:
Zastanów się nad studentem, kursem, stowarzyszeniem klasy. Studenci są kojarzeni z kursem poprzez ocenę. Zwykle jest to skojarzenie wiele do wielu między Studentem a Kursem z dodatkowym polem w tabeli skojarzeń o nazwie grade (tabele asocjacji zawierają dane typu klasa, tabele przecięcia nie mają ładunku i są określane w MSDN jako tabele czysto sprzężenia na dzierżawa w jednym miejscu):
Student(Identyfikator studenta , ....)
Kurs(Identyfikator kursu , ...)
Biorąc(Identyfikator ucznia) , Identyfikator kursu , ocena)
Jeśli ktoś popełni błąd podczas wprowadzania danych z listy rozwijanej i umieści ucznia na niewłaściwych zajęciach, chcesz, aby zmienili to później, ponownie wybierając menu rozwijane i wybierając inny kurs. W tle będziesz musiał usunąć obiekt EF z tabeli Taking i odtworzyć go bez utraty oceny, jeśli taka istnieje. Po prostu zmień klucz obcy Identyfikator kursu wydaje się lepszą alternatywą. Wymyśl własne skojarzenie, jeśli to wydaje się wymyślone, ale jako profesor było to dla mnie naturalne.
Wniosek:Kiedy masz ciąg relacji, lepiej nie zezwalać na kaskadowanie i/lub zmianę FK, ale istnieją rozsądne/logiczne scenariusze, w których jest to potrzebne, nawet jeśli nie jest to zalecane jako najlepsza praktyka w ogólnie .
Ten problem może objawiać się następującymi wyjątkami w zależności od tego, czy zmieniasz odpowiednio właściwość nawigacji, czy właściwość klucza w modelu:
Wystąpiło naruszenie ograniczenia integralności referencyjnej:Właściwość klucza podstawowego, która jest częścią ograniczenia integralności referencyjnej, nie może zostać zmieniona, gdy obiekt zależny jest niezmieniony, chyba że jest ustawiony na obiekt główny powiązania. Główny obiekt musi być śledzony i nie oznaczony do usunięcia.
Właściwość „X” jest częścią kluczowych informacji o obiekcie i nie może być modyfikowana.