2009-04-22 11 views
6

Pracuję nad małym projektem edukacyjnym do wykonywania perst.net.Wiele do wielu relacji obiekt do obiektu w C#

Mamy drobny problem, projekt, że jest to, jak najlepiej rozwiązać relację między dwoma klasami obiektów, czyli uczestnik i mistrzostwa. Jest wiele do wielu relacji jako uczestnik mogą wziąć udział w wielu mistrzostwach i mistrzostwach może mieć wielokrotności uczestników.

Proszę doradzić jak zrobić to najlepiej w języku C#, czy powinienem używać klasy technicznej "relacyjnej DB jak"?

Odpowiedz

1

Nie jestem pewien, czy to działa dla swojego projektu lub wymagań, ale może to być możliwe ...

Oczywiście wiele-do-wielu jest najłatwiejszy do reprezentowania z trzecim obiektem, który zarządza relacji . W twoim przypadku będzie to uczestnik mistrzostw. Zamiast zbierać kolekcję w klasie uczestnika, która posiada mistrzostwa i odwrotnie, poproś ich, aby zatrzymali instancję tej trzeciej klasy. Obiekt championship uczestnik zarządza tą relacją. Następnie może być serializowany do bazy danych bezpośrednio jako tablica połączeń.

4

Możesz mieć dowolne powiązanie, w którym dana pozycja może mieć wiele elementów powiązanych z nią przy użyciu właściwości IEnumerable (lub innych kolekcji). W przykładzie będzie to wyglądać następująco:

class Participant { 
    public IEnumerable<Championship> Championships { 
     get { 
     return _championships; 
     } 
    } 
    private List<Championship> _championships; 
} 

kilka ważnych rzeczy do pamiętać:

  • zawsze sprawiają, że ta właściwość tylko do odczytu. Czasami jest to mylące dla ludzi, zwłaszcza jeśli masz coś, co można zmodyfikować tak, jak zwróciło ICollection, a nie IEnumerable. Utworzenie właściwości tylko do odczytu nie zapobiega modyfikacji kolekcji , ale modyfikacji całej listy .

  • Strategie ładowania - zauważysz w powyższym przykładzie kolekcja nie jest inicjalizowana. Zwykle robisz to albo w konstruktorze, albo gdy właściwość jest dostępna po raz pierwszy (nazywana leniwą instancją) - ogólnie rzecz biorąc, leniwe tworzenie wystąpień zwiększa złożoność, ale może zwiększyć wydajność, szczególnie jeśli kolekcja ta nie jest często używana lub masz wiele takich typów nieruchomości.

  • Generalnie dobrze jest wybrać klasę, aby "utrzymać" drugą klasę w przypadku wielu do wielu (np. Uczestnicy mają mistrzowskie właściwości, ale mistrzostwa nie mają właściwości uczestników lub odwrotnie). Ogranicza to ilość kodu, który musisz napisać, oraz zmniejsza złożoność i powierzchnię z bazą danych. Jeśli wywołanie jest potrzebne w innym kierunku, rozważ wywołanie metody, a nie właściwość. Pamiętaj, że wiele do wielu z sensu relacyjnego nie musi oznaczać, że jest to powszechny przypadek użycia (Jako użytkownik, mogę chcieć dodać uczestników do mistrzostw, a nie uczestników mistrzostw)

  • Jeśli Twoja kolekcja jest modyfikowalne, pamiętaj, że wysłanie Save oznacza, że ​​kolekcje znajdujące się pod nim również powinny zostać zmodyfikowane, jeśli zostały zmienione.Może to znacznie zwiększyć złożoność (w przeszłości używałem wewnętrznych list do przechowywania dodanych/usuniętych elementów)

+0

Wow. Świetny anwser. –

8

Jeśli szukasz podejścia zorientowanego obiektowo (lub opartego na domenie), trzeci obiekt do obsługi "sprzężenia" jest całkowicie niewłaściwym sposobem rozwiązania tego problemu. Można użyć ILists/Enumerables z Add ... metod, aby obsłużyć to następująco:

public class Participant 
{ 
    private readonly IList<Championship> _championships = new List<Championship>(); 

    public IEnumerable<Championship> Championships 
    { 
     get { return _championships; } 
    } 

    internal void AddChampionship(Championship championship) 
    { 
     if (!_championships.Contains(championship)) 
      _championships.Add(championship); 
    } 
} 

public class Championship 
{ 
    private readonly IList<Participant> _participants = new List<Participant>(); 

    public IEnumerable<Participant> Participants 
    { 
     get { return _participants; } 
    } 

    public void AddParticipant(Participant participant) 
    { 
     if (_participants.Contains(participant)) return; 
     _participants.Add(participant); 
     participant.AddChampionship(this); 
    } 
} 

Kluczem tutaj jest, aby upewnić się zarządzać relację tylko z jednej strony - na przykład w tym przypadku byłoby to wywołanie championship.AddParticipant()

+1

Świetna odpowiedź! Ostatnie zdanie jest kluczowe ... powinieneś zrobić to odważnie! +1 – Cerebrus

Powiązane problemy