2016-10-18 34 views
5

Aby dać pojęcie o czym mówię, rozważ podmiot (w moim przypadku jest to Task), który może być powiązany z dowolną liczbą innych elementów w systemie. Dla naszych celów powiedzmy, że zadanie może być związane z:Baza danych SQL Server - jak obsługiwać tabelę, która może być powiązana z dowolną liczbą innych tabel?

  • Projekt
  • Konto
  • biletów
  • Osoba
  • itp

Wszystkie te reprezentowane są z własnych tabel w bazie danych. Teraz zadanie może być potencjalnie powiązane z jednym z nich, a ze względu na aktywny rozwój systemu, lista potencjalnych połączeń będzie nadal rosła stosunkowo szybko. Uwaga: są to relacje od 1 do wielu - zadanie można połączyć tylko z jednym z nich naraz, ale jedno konto może mieć przypisane wiele zadań.

Rozważałem teraz kilka opcji, ale nie uważam się za ekspertów od projektowania baz danych, więc pomyślałem, że sięgnę. Opcje, jakie uznała więc narazie to:

  • Klucz obcy dla każdego łącza w tabeli Task, a my po prostu trzeba zachować dodanie kolumny. Jednak ponieważ zadanie nie może być połączone z więcej niż jednym z nich na raz, spowoduje to wiele kolumn FK z wartościami NULL. Będzie to również wymagało nowej kolumny i regeneracji naszego modelu bazy danych w naszej aplikacji za każdym razem, gdy dodamy nowy link.

  • Pojedyncza kolumna Task który działa jako klucz obcy, ale to inną kolumnę określającą link type, więc podczas odpytywania przeciw niemu możemy określić, który przyłącza się zdarzyć w zależności od rodzaju. Tak więc zarówno Konto, jak i ID osoby będą w tej kolumnie dla swoich zadań, ale kolumna typu połączenia określa, czy ID jest osobą czy kontem. Jest to dla mnie bardzo ryzykowne i oczywiście ograniczenia nie mogą być egzekwowane przez bazę danych.

  • Inne opcje?

chciałbym, jeśli ktoś był w stanie wskazać mi w kierunku „czystszego” projektu, ale jeśli nie, to wielokrotne kolumny działającego w charakterze ograniczeń FK, ale pozwalając NULL być najlepszym?

Z góry dziękuję!

+0

Przed podobnym wyzwaniem stanęłam kilka lat temu. Bez większego zastanowienia zdecydowałem się na drugą opcję. Zamiast używać object_id w sys.object, utworzyłem nową tabelę, która zawiera stałą, która tabela. Słyszałem gdzieś, że ten projekt jest zły, ale nigdy nie słyszałem, dlaczego. Pięć lat później ten typ linków był używany prawie wszędzie w aplikacji (komentarze, dokumenty, parametry itp.). W pewnym sensie stał się on rdzeniem aplikacji. Nie spodziewałem się tego w tamtym czasie, ale jestem dumny z tego, jak się rozwinęło. – AXMIM

+0

Po moim poprzednim komentarzu, ponieważ już tam nie pracuję, więc nie mogę stwierdzić, czy teraz szkodzą temu efektowi. Trzymał się dość solidnie przez 5 lat. Muszę jednak przyznać, że widziałem serwer SQL, który wykonał jakiś dziwny plan zapytania jeden lub dwa razy z tego powodu i że jest tu kilka małych wad. Również struktura podmiotu nie była w pobliżu. Nie jestem pewien, czy zaufałbym EF do obsługi tych połączeń. – AXMIM

+2

To jest nowa instancja powtarzającego się pytania * stowarzyszeń polimorficznych *. Gdy znasz już oficjalny termin, łatwo jest znaleźć sposób na zrobienie tego. –

Odpowiedz

0

Właściwie przyjętym standardem jest tabela REF lub XREF. Tak więc, na przykład między Zadaniem a Projektem, masz tabelę z identyfikatorem tabeli, kluczem obcym dla zadania i kluczem obcym dla projektu.

Zasadniczo kojarzysz projekt i zadanie według ID i po prostu dodasz nowy wpis za każdym razem, gdy potrzebujesz nowego powiązania. Jeśli istnieją konkretne informacje na temat tej relacji, będzie ona żyć w tej tabeli ze związkiem.

3

Używałbym pierwszej opcji.

Wady:

  1. Dodaj nową kolumnę po dodaniu nowej tabeli - jak jesteś już edycję bazy danych, dodając nową tabelę, dodając jedną kolumnę nie powinno być problemem.
  2. Wartości NULL w wielu kolumnach - Nie ma to dużego wpływu na wydajność ani na nic innego. Możesz użyć wartości domyślnych zamiast NULL, jeśli pasuje ci to lepiej. Patrz na to pytanie (SQL Server - Performance/Size Drawbacks of Null Columns) i odpowiedzi

Ale z drugiej strony, można uzyskać bardziej rozbudowane relacje, dołącza zrozumiałe, znacznie bardziej odpowiednie mapowania Entity Framework, łatwiejsze zapytań mrówka itd

+0

Zgadzam się z tym - uważam, że tak właśnie zamierzam iść. Może to być trochę przeciwne pisaniu w naszej aplikacji, ale jak zauważyłeś, korzyści znacznie przewyższają minusy. – CTDev

+0

@CTDev, cieszę się, że sformułowałem pewne zdanie, ale upewnij się, że dobrze się nim zajmuję przed jego wdrożeniem. Spróbuj wyszukać * skojarzenia polimorficzne *, jak zauważył GiladGreen. –

+1

Przeczytałem o tym i zdecydowanie znalazłem o wiele lepsze rozwiązanie. Wdrażając tabelę podobną do interfejsu w OOP (nazwałem ją "Taskable"), udało mi się zbudować relację, w której, na każdym wkładzie, aby powiedzieć Konto, wstawiam również do Tassuble, klucz podstawowy z konta, który był właśnie wstawiony. Zadanie następnie odwołuje się do identyfikatorów w Taskable, a ja implementuję FK z PK w kontach, projektach itp. Robiąc to, tak długo, jak PK w moich tabelach są identyfikatorami GUID, mam bezpośrednią ścieżkę z zachowaną integralnością referencyjną. Dużo się dzisiaj nauczyłem! – CTDev

1

znalazłem w przeszłość, która przy odpowiednim uwzględnieniu projektu nie jest konieczna. Na przykład konto może mieć wiele projektów. Konto może mieć wiele osób. Projekt może mieć wiele zadań. Tak więc zadania dotyczą tylko projektów.

Jeśli to naprawdę nie działa, można rozważyć tabelę zadań dla każdego typu. Zadania projektu, zadania związane z kontem itp. Poprawi to wydajność zapytań.

Następnie chciałbyś, aby reguła domeny zapewniała, że ​​wszystkie tabele zadań są zgodne z określonym schematem.

Dowiedziałem się o regule domeny w college'u, ale nigdy nie zaimplementowałem jej w świecie rzeczywistym, więc nie wiem, jak można to zrobić na serwerze SQL. W rzeczywistych scenariuszach zawsze się sprawdzał, jak to określiłem w pierwszym akapicie.

Mam nadzieję, że to pomoże. W przeciwnym razie pozostałe dwie odpowiedzi mają tutaj sens.

+0

Dzięki za wgląd - to dziwna pozycja, w której zadanie można powiązać z projektem (który z kolei jest powiązany z kontem), a zatem jest ono również powiązane z kontem (pośrednio). Jednakże chcą również, aby zadanie mogło być powiązane bezpośrednio z kontem. Nie jestem w 100% pewien, jak sobie z tym poradzić, ponieważ obiekt zadania jest taki sam, bez względu na to, do czego jest związany, więc miałem nadzieję użyć pojedynczej tabeli zadań, ale jednocześnie integralność referencyjna staje się problemem. Powiedział, że przyjrzę regułę domeny, dzięki za informacje! – CTDev

+0

Myślę, że kluczem jest to, że "chcą, aby zadanie można było bezpośrednio powiązać z kontem". Odkryłem, że badanie reguł biznesowych u interesariuszy prawie zawsze pozwala na znormalizowany projekt. Zazwyczaj można to zrobić za pomocą interfejsu użytkownika i raportów, a większość frameworków podłącza się do znormalizowanych baz danych, dzięki czemu opłaca się w dłuższej perspektywie. –